Skip to main content
Glama
ibrahimhajjaj

seo-console-mcp

seo-mcp

seo-mcp is a stdio Model Context Protocol server for Google Search Console, PageSpeed Insights, and on-page SEO audits. It gives MCP clients forty-three tools covering verified Search Console properties and the other places products get discovered, the App Store, Google Play, WordPress.org, Google Ads, and real-user Core Web Vitals, while keeping the HTML audit, PageSpeed, IndexNow, keyword ideas, and WordPress.org tools usable without Google service account credentials. Every tool also runs from the command line, so a result can be written to a file instead of into a model's context, and snapshot records Search Console, the App Store, Google Play and WordPress.org at one moment so a later run can diff against it.

https://github.com/user-attachments/assets/66bbd628-d267-421f-9400-633b696bbd53

Requirements

  • Node.js 20.18.1 or newer

  • gcloud only if you use the setup wizard

What else you need depends on which tools you use. The setup wizard covers Search Console and PageSpeed; the App Store, Google Play, and Chrome UX Report tools each need a credential you create yourself.

Tools

Needs

Where it comes from

seo_audit, audit_site, keyword_ideas (without siteUrl), wporg_plugin

nothing

public endpoints

pagespeed

optional SEO_MCP_PAGESPEED_KEY

setup wizard --pagespeed-key, or a Google Cloud API key

crux_field_data, crux_history

SEO_MCP_CRUX_KEY (or the PageSpeed key if it may call the CrUX API)

Google Cloud API key

indexnow_submit

SEO_MCP_INDEXNOW_KEY

any key you host at /<key>.txt

Search Console tools, snapshot properties

service account key

setup wizard, then add the account to the property

snapshot, list_snapshots, compare_snapshots

optional SEO_MCP_SNAPSHOT_DIR

where snapshot files live, defaulting to ~/.config/seo-mcp/snapshots

verify

CLOUDFLARE_API_TOKEN

Cloudflare, Zone.DNS:Edit

app_store_listing, app_store_discovery, app_store_reviews

SEO_MCP_ASC_KEY_PATH, SEO_MCP_ASC_KEY_ID, SEO_MCP_ASC_ISSUER_ID

App Store Connect team key, any role that can read the app

app_store_sales

the above plus SEO_MCP_ASC_VENDOR_NUMBER

team key created with Admin, Finance, or Sales and Reports

play_store_stats

SEO_MCP_PLAY_BUCKET, SEO_MCP_PLAY_CREDENTIALS

service account with read access to the reporting bucket

play_vitals

SEO_MCP_PLAY_CREDENTIALS

service account invited in Play Console with app quality access

the ads_ tools

GOOGLE_ADS_DEVELOPER_TOKEN, GOOGLE_ADS_CLIENT_ID, GOOGLE_ADS_CLIENT_SECRET, GOOGLE_ADS_REFRESH_TOKEN, GOOGLE_ADS_CUSTOMER_ID

a Google Ads developer token and an OAuth client with a refresh token

Related MCP server: gsc-mcp

Install and build

npm install
npm run build

Run the local server with:

node /absolute/path/to/seo-mcp/dist/index.js

The package is published on npm as seo-console-mcp; it installs a command named seo-mcp. An MCP client can launch it through:

npx -y seo-console-mcp

The running server uses stdout exclusively for the MCP wire protocol. Diagnostics are written to stderr.

Setup wizard

From a local checkout:

npm run setup

Or with npx:

npx -y seo-console-mcp setup

For an unattended project choice or a custom key location:

seo-mcp setup --project my-seo-project --key /absolute/path/seo-mcp.key.json

The wizard also offers an optional PageSpeed Insights API key for higher quota. It is opt-in: use --pagespeed-key to create one without a prompt, or --no-pagespeed-key to skip the prompt explicitly. Non-interactive runs skip it unless --pagespeed-key is provided.

The wizard is safe to rerun. It:

  1. Checks for gcloud. If it is absent, it prints manual instructions and exits successfully without changing anything.

  2. Uses the active authenticated account or runs gcloud auth login.

  3. Uses the current project, a supplied --project, or asks for a project ID. It creates the project if it does not exist and selects it.

  4. Enables searchconsole.googleapis.com, pagespeedonline.googleapis.com, and siteverification.googleapis.com.

  5. Reuses or creates the seo-mcp service account.

  6. Reuses an existing key or creates seo-mcp.key.json.

  7. Optionally creates a project-scoped API key restricted to PageSpeed Insights.

  8. Prints the required Search Console permission step and ready-to-copy client configurations.

The wizard never prints the service account key contents. When PageSpeed key creation is requested and succeeds, it prints that key once in the final client configuration. The generated *.key.json filename is ignored by Git.

Granting the service account Search Console access

The Search Console API has no endpoint for adding a user to a property, so the service account has to become a verified owner of the domain itself. There are two ways to do that.

Automated (Cloudflare DNS)

If the domain's DNS is on Cloudflare, verify does the whole thing: it asks Google for a verification token, writes the TXT record through the Cloudflare API, waits for verification, and registers the property.

export CLOUDFLARE_API_TOKEN=...   # a token scoped to Zone.DNS:Edit for the zone
seo-mcp verify getpsst.app another-domain.com

The token can also be passed with --cf-token, and the key path with --credentials (otherwise GOOGLE_APPLICATION_CREDENTIALS / SEO_MCP_CREDENTIALS is used). The command is idempotent: the TXT record is left in place (Google re-checks it), so re-running a domain is safe. Leave the record in DNS or ownership is lost.

verify reads the token from CLOUDFLARE_API_TOKEN or CF_API_TOKEN (or --cf-token) and never stores or logs it, so any secret store that can export an environment variable works. The token needs Zone -> DNS -> Edit and Zone -> Zone -> Read (the "Edit zone DNS" template), scoped to the zones you verify. To keep it out of shell history:

macOS (Keychain):

security add-generic-password -a "$USER" -s cloudflare-dns-edit -l "Cloudflare DNS Edit" -U -w   # store once, hidden prompt
CLOUDFLARE_API_TOKEN=$(security find-generic-password -s cloudflare-dns-edit -w) seo-mcp verify example.com

Linux (libsecret, or pass):

secret-tool store --label="Cloudflare DNS Edit" service cloudflare-dns-edit   # store once, hidden prompt
CLOUDFLARE_API_TOKEN=$(secret-tool lookup service cloudflare-dns-edit) seo-mcp verify example.com

Windows (PowerShell SecretManagement):

Set-Secret -Name cloudflare-dns-edit -Secret (Read-Host -AsSecureString)   # store once, hidden prompt
$env:CLOUDFLARE_API_TOKEN = Get-Secret -Name cloudflare-dns-edit -AsPlainText; seo-mcp verify example.com

Manual

Add the service account as an owner in the Search Console UI:

Search Console -> your property -> Settings -> Users and permissions -> Add user
  seo-mcp@PROJECT_ID.iam.gserviceaccount.com  ->  Owner

Use the exact service account email printed by the wizard. Owner access is needed because submit_sitemap is a write operation.

Manual Google Cloud fallback

If gcloud is unavailable, create the credentials manually or run these commands after installing it:

gcloud auth login
gcloud projects create YOUR_PROJECT_ID
gcloud config set project YOUR_PROJECT_ID
gcloud services enable searchconsole.googleapis.com pagespeedonline.googleapis.com siteverification.googleapis.com
gcloud iam service-accounts create seo-mcp --display-name="SEO MCP"
gcloud iam service-accounts keys create ./seo-mcp.key.json \
  --iam-account=seo-mcp@YOUR_PROJECT_ID.iam.gserviceaccount.com

If the project already exists, skip gcloud projects create. Then grant the service account Search Console access (see above) and configure the absolute key path in the MCP client.

Authentication

The Search Console tools use google.auth.GoogleAuth with both scopes:

  • https://www.googleapis.com/auth/webmasters

  • https://www.googleapis.com/auth/webmasters.readonly

Credential lookup order is:

  1. --credentials /absolute/path/key.json

  2. SEO_MCP_CREDENTIALS

  3. GOOGLE_APPLICATION_CREDENTIALS

  4. ~/.config/seo-mcp/seo-mcp.key.json (or $XDG_CONFIG_HOME/seo-mcp/...) if it exists. This is the default location the setup wizard writes to, so a standard install needs no configuration.

For example:

node dist/index.js --credentials /absolute/path/seo-mcp.key.json

pagespeed is public and does not use the service account. Set SEO_MCP_PAGESPEED_KEY or pass apiKey to that tool for a higher PageSpeed Insights quota. seo_audit, audit_site, and indexnow_submit also need no Google credentials; indexnow_submit instead takes an IndexNow key via key or SEO_MCP_INDEXNOW_KEY. keyword_ideas only needs them when siteUrl is passed for the Search Console cross-reference. App Store Sales and Trends reads SEO_MCP_ASC_VENDOR_NUMBER. The Chrome UX Report tools read SEO_MCP_CRUX_KEY, falling back to SEO_MCP_PAGESPEED_KEY when the same key is allowed to call chromeuxreport.googleapis.com. snapshot, list_snapshots and compare_snapshots keep their documents in SEO_MCP_SNAPSHOT_DIR, defaulting to ~/.config/seo-mcp/snapshots, and cannot read or write outside it. The table under Requirements maps every tool to what it needs.

Security model

  • Verifying a domain makes the service account a verified Owner. Owners can change Search Console settings and submit removal (deindex) requests, so treat the key as a sensitive credential even though most tools here only read.

  • Keep the key local. It lives at the GOOGLE_APPLICATION_CREDENTIALS path (chmod 600 recommended). Never bundle it in a published package, a container image, or a CI secret store. If it leaks, anyone with it has owner control of every verified property.

  • Leave the google-site-verification TXT record in DNS. Google re-checks it; deleting it revokes ownership.

  • No secret is logged. The wizard and verify print credential paths only, never key or token contents.

  • Revoking is easy. Relinquish ownership from the Search Console UI (or siteVerification.webResource.delete), and rotate the key with gcloud iam service-accounts keys delete.

  • seo_audit only fetches public hosts. The target URL and every redirect hop is resolved and refused if it lands on a loopback, private, link-local, or other non-public address, so a model cannot be steered into fetching internal services or cloud metadata. The address is validated again at connection time (the socket is pinned to the validated address), so a DNS-rebinding host cannot present a public address at validation and a private one at connect. Set SEO_MCP_ALLOW_PRIVATE_HOSTS=1 to audit internal or staging hosts you trust. This is not a substitute for network-level isolation; run the server behind egress controls if you audit untrusted URLs on a host with reachable internal services.

Claude Code plugin

This repo is also a Claude Code plugin that bundles the MCP server and adds three slash commands over it. From Claude Code:

/plugin marketplace add ibrahimhajjaj/seo-console-mcp
/plugin install seo-console@verdelic

It registers the MCP server (via npx -y seo-console-mcp) and adds:

  • /seo-console:triage <siteUrl>: full property triage with a prioritized action plan

  • /seo-console:content <siteUrl>: content to create or improve, backed by Search Console data

  • /seo-console:launch <siteUrl>: pre-launch / launch SEO readiness check

The server finds your service-account key automatically at the default location (~/.config/seo-mcp/seo-mcp.key.json, where the setup wizard writes it), so no configuration is needed for a standard install. For a key elsewhere, set GOOGLE_APPLICATION_CREDENTIALS (and SEO_MCP_PAGESPEED_KEY for higher PageSpeed quota) in the environment Claude Code runs in. The seo_audit and pagespeed tools work with no credentials at all.

To try it from a local checkout without a marketplace: claude --plugin-dir ..

Claude Code (MCP server only)

Register the local build for the current user:

claude mcp add --scope user seo-mcp --env GOOGLE_APPLICATION_CREDENTIALS=/abs/path/seo-mcp.key.json -- node /abs/path/seo-mcp/dist/index.js

The -- separator is mandatory. It separates Claude Code options from the MCP server command.

Or with npx (no local build):

claude mcp add --scope user seo-mcp --env GOOGLE_APPLICATION_CREDENTIALS=/abs/path/seo-mcp.key.json -- npx -y seo-console-mcp

User scope makes the server available across your projects. Use --scope project when the registration should be shared through the current project's .mcp.json instead.

Project .mcp.json:

{
  "mcpServers": {
    "seo-mcp": {
      "type": "stdio",
      "command": "node",
      "args": ["/abs/path/seo-mcp/dist/index.js"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "/abs/path/seo-mcp.key.json"
      }
    }
  }
}

Claude Desktop

Add the same server entry under mcpServers in Claude Desktop's configuration file, then restart Claude Desktop:

{
  "mcpServers": {
    "seo-mcp": {
      "command": "node",
      "args": ["/abs/path/seo-mcp/dist/index.js"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "/abs/path/seo-mcp.key.json"
      }
    }
  }
}

To run without a local build, use "command": "npx" and "args": ["-y", "seo-console-mcp"].

Resources

seo://properties returns the Google Search Console properties available to the service account as JSON. It calls Search Console on every read, so the result is always current.

Prompts

MCP clients surface these prompts as starting points a user can pick for common SEO workflows:

  • seo_triage confirms a property, analyzes recent performance and opportunities, audits the site, and produces an impact-versus-effort action plan.

  • content_opportunities groups evidence-backed recommendations into content to create and existing content to improve.

  • launch_seo_check produces a go/no-go checklist for technical and indexing readiness before launch.

Tools

Every tool validates its input with Zod. Tool failures return an MCP error result instead of terminating the server. Google API status, message, and reason are included when available. A Search Console 403 also explains how to grant the service account property access.

list_properties

Lists every Google Search Console property the service account can access, returning each property's exact siteUrl and permissionLevel. It takes no input. Service-account credentials are required, unlike pagespeed, seo_audit, audit_site, and indexnow_submit.

This tool takes no parameters.

search_analytics

Queries searchanalytics.query and returns a compact ranked table plus structured rows.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-06-01",
  "endDate": "2026-06-28",
  "dimensions": ["query", "page"],
  "rowLimit": 100,
  "maxTableRows": 25,
  "dimensionFilterGroups": [
    {
      "groupType": "and",
      "filters": [
        { "dimension": "query", "operator": "contains", "expression": "seo" }
      ]
    }
  ],
  "type": "web"
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property, such as https://example.com/ or sc-domain:example.com

startDate

string

no

Start date in YYYY-MM-DD; defaults to 28 days ago

endDate

string

no

End date in YYYY-MM-DD; defaults to today

dimensions

list of one of query, page, country, device, date, searchAppearance

no

["query"]

Dimensions used to group results

rowLimit

number

no

25

Maximum rows to return

startRow

number

no

0

Zero-based row to start from, for paging through a large result

maxTableRows

number

no

25

Cap rows shown in the text table; structured rows are always complete. 0 = summary only.

dimensionFilterGroups

JSON list

no

Search Console dimension filters

type

one of web, image, video, news, discover, googleNews

no

Result type. discover is the Discover feed and googleNews is the Google News app and news.google.com, not the News tab in Search. Both support fewer dimensions than web: neither reports a query dimension

dataState

one of full, all

no

full = finalized data (default, ~2-3 day lag); all = include recent partial data

aggregationType

one of auto, byProperty, byPage

no

How Search Console aggregates rows

maxTableRows caps only the text table; the structured rows stay complete, so 0 returns the totals with no table rather than an empty result. discover and googleNews support fewer dimensions than web: neither reports a query dimension.

keyword_ideas

Expands a seed through Google Autocomplete and returns normalized, deduplicated keyword ideas grouped by discovery family. It uses the public autocomplete endpoint, needs no extra API key, and works without Google credentials unless siteUrl is provided. With a Search Console property, it labels ideas already ranking with their average position, clicks, and impressions over the selected lookback window.

{
  "seed": "technical seo",
  "siteUrl": "sc-domain:example.com",
  "language": "en",
  "country": "us",
  "expansions": ["alphabet", "questions", "prepositions", "comparisons"],
  "days": 90,
  "limit": 100
}

Parameter

Type

Required

Default

Description

seed

string

yes

Seed keyword to expand

siteUrl

string

no

Optional Search Console property used to identify queries already ranking

language

string

no

"en"

Autocomplete interface language passed as hl

country

string

no

Autocomplete country passed as gl

expansions

list of one of alphabet, questions, prepositions, comparisons

no

["alphabet","questions","prepositions","comparisons"]

Suggestion expansion families to run beyond the bare seed

days

number

no

90

Search Console lookback window in days

limit

number

no

100

Maximum keyword ideas to return

All four expansion families run by default. days defaults to 90 and is capped at 480; limit defaults to 100 and is capped at 500. Individual autocomplete failures are counted without discarding successful suggestions.

search_opportunities

Finds high-impression queries in striking distance of stronger rankings. It groups by query and page, defaults to positions 5 through 20, and returns opportunities ranked by impression-weighted position.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-06-01",
  "endDate": "2026-06-28",
  "minPosition": 5,
  "maxPosition": 20,
  "minImpressions": 100,
  "limit": 25
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property to analyze

startDate

string

no

Start date in YYYY-MM-DD; defaults to the latest 28-day window

endDate

string

no

End date in YYYY-MM-DD; defaults to today

minPosition

number

no

Lowest average position to include; defaults to 5

maxPosition

number

no

Highest average position to include; defaults to 20

minImpressions

number

no

Minimum impressions required; defaults to 10

limit

number

no

Maximum opportunities to return; defaults to 50

compare_search_periods

Compares a selected window with the immediately preceding equal-length window. It returns the largest click gainers and losers grouped by query or page.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-06-01",
  "endDate": "2026-06-28",
  "by": "query",
  "limit": 25
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property to analyze

startDate

string

no

Start date in YYYY-MM-DD; defaults to the latest 28-day window

endDate

string

no

End date in YYYY-MM-DD; defaults to today

by

one of query, page

no

"query"

Dimension used to compare performance

limit

number

no

Maximum gainers and losers to return; defaults to 50 each

ctr_gaps

Finds high-impression queries or pages whose CTR trails the average for rows at the same rounded position. The missed-click estimate helps prioritize title and description rewrites.

{
  "siteUrl": "sc-domain:example.com",
  "by": "page",
  "minImpressions": 250,
  "limit": 25
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property to analyze

startDate

string

no

Start date in YYYY-MM-DD; defaults to the latest 28-day window

endDate

string

no

End date in YYYY-MM-DD; defaults to today

by

one of query, page

no

"query"

Dimension used to identify CTR gaps

minImpressions

number

no

Minimum impressions required; defaults to 100

limit

number

no

Maximum gaps to return; defaults to 50

query_cannibalization

Finds queries for which multiple pages receive Search Console impressions. Results group the competing pages and rank groups by total impressions.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-06-01",
  "endDate": "2026-06-28",
  "minImpressions": 25
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property to analyze

startDate

string

no

Start date in YYYY-MM-DD; defaults to the latest 28-day window

endDate

string

no

End date in YYYY-MM-DD; defaults to today

minImpressions

number

no

Minimum impressions per query-page row; defaults to 10

list_sitemaps

Lists sitemap path, submission/download times, pending/index flags, warning/error counts, and content counts.

{
  "siteUrl": "https://www.example.com/"
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property

submit_sitemap

Submits a sitemap and refreshes its current state. This is a write operation. If submission succeeds but the state refresh fails, the result still confirms that Google accepted the write and reports the refresh warning.

{
  "siteUrl": "sc-domain:example.com",
  "feedpath": "https://www.example.com/sitemap.xml"
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property

feedpath

string

yes

Absolute URL of the sitemap to submit

dryRun

boolean

no

false

If true, report what would be submitted without writing to Search Console

delete_sitemap

Removes a submitted sitemap from a Search Console property. This is a write operation. Set dryRun to true to preview the removal without changing Search Console.

{
  "siteUrl": "sc-domain:example.com",
  "feedpath": "https://www.example.com/sitemap.xml",
  "dryRun": true
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property

feedpath

string

yes

Absolute URL of the sitemap to remove

dryRun

boolean

no

false

If true, report what would be removed without writing to Search Console

inspect_url

Returns index coverage, verdict, robots state, indexing state, crawl time, fetch state, Google and user canonicals, mobile usability, and rich-result status.

{
  "siteUrl": "sc-domain:example.com",
  "inspectionUrl": "https://www.example.com/products/widget"
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property containing the inspected URL

inspectionUrl

string

yes

Fully qualified URL to inspect

index_coverage

Fetches a sitemap and checks a bounded set of its direct page URLs with Google's URL Inspection API. It returns indexed, not-indexed, and failed counts, the not-indexed URLs and coverage states, full per-URL results, and whether the result was truncated. Sitemap indexes are not followed into child sitemaps.

{
  "siteUrl": "sc-domain:example.com",
  "sitemapUrl": "https://www.example.com/sitemap.xml",
  "maxUrls": 20,
  "concurrency": 3
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property containing the sitemap URLs

sitemapUrl

string

yes

Fully qualified sitemap URL to inspect

maxUrls

number

no

20

Maximum URLs to inspect

concurrency

number

no

3

Concurrent URL Inspection requests

maxUrls defaults to 20 and has a hard maximum of 50. concurrency defaults to 3 and has a hard maximum of 5. These limits protect the URL Inspection API quota, which is approximately 2,000 queries per day and 600 per minute for each property.

request_recrawl

Checks URLs with the URL Inspection API and, when some are not indexed, resubmits the covering sitemap. That resubmission is Google's only supported bulk recrawl signal: there is no request-indexing API, and the Search Console UI's Request Indexing button has no programmatic equivalent. URLs come from urls or are read from sitemapUrl; the sitemap to resubmit is feedpath, defaulting to sitemapUrl. This is a write operation. Set dryRun to true to inspect and report without resubmitting.

{
  "siteUrl": "sc-domain:example.com",
  "sitemapUrl": "https://www.example.com/sitemap.xml",
  "maxUrls": 20,
  "dryRun": true
}

Parameter

Type

Required

Default

Description

siteUrl

string

yes

Search Console property containing the URLs

urls

list of string

no

Explicit URLs to check; omit to read them from sitemapUrl

sitemapUrl

string

no

Sitemap to read URLs from; also the default sitemap to resubmit

feedpath

string

no

Sitemap to resubmit when unindexed URLs are found; defaults to sitemapUrl

maxUrls

number

no

20

Maximum sitemap URLs to inspect

concurrency

number

no

3

Concurrent URL Inspection requests

dryRun

boolean

no

false

If true, inspect and report without resubmitting the sitemap

It shares the index_coverage caps (maxUrls up to 50, concurrency up to 5) because both draw on the same URL Inspection quota. Resubmission only prompts a recrawl of pages whose sitemap lastmod is fresh, so keep lastmod accurate for changed URLs.

indexnow_submit

Submits up to 10,000 changed URLs in one call to an IndexNow endpoint. Participating engines (Bing, Yandex, Naver, Seznam, Yep) share submissions with each other. Google does not use IndexNow; use request_recrawl for Google. This is a write operation and supports dryRun. It needs no Google credentials.

{
  "urls": ["https://www.example.com/new-page", "https://www.example.com/updated-page"],
  "key": "your-indexnow-key"
}

Parameter

Type

Required

Default

Description

urls

list of string

yes

Changed page URLs; one submission covers one host

key

string

no

IndexNow key; defaults to SEO_MCP_INDEXNOW_KEY. The same key must be hosted on the site as a text file at https:///.txt (or at keyLocation) containing only the key

keyLocation

string

no

URL of the hosted key file when it is not https:///.txt

endpoint

one of api.indexnow.org, www.bing.com, yandex.com, searchadvisor.naver.com, search.seznam.cz, indexnow.yep.com

no

"api.indexnow.org"

IndexNow endpoint to notify; participating engines share submissions

dryRun

boolean

no

false

If true, report what would be submitted without notifying the endpoint

All URLs in one submission must share one host. The key is any 8-128 character value of letters, digits, or dashes, passed as key or SEO_MCP_INDEXNOW_KEY, and must be hosted as a text file containing exactly the key at https://<host>/<key>.txt (or at keyLocation on the same host). Because key file URLs conventionally contain the key, neither the key nor keyLocation is ever echoed in tool output. endpoint defaults to api.indexnow.org; a submission to any participating endpoint reaches all of them.

pagespeed

Returns CrUX field data when available, including LCP, CLS, INP or FID, FCP, and TTFB. It also returns Lighthouse category scores and up to ten highest-savings opportunities.

{
  "url": "https://www.example.com/",
  "strategy": "mobile",
  "category": ["performance", "seo", "accessibility", "best-practices"]
}

Parameter

Type

Required

Default

Description

url

string

yes

Public page URL to analyze

strategy

one of mobile, desktop

no

"mobile"

Lighthouse device strategy

category

list of one of performance, seo, accessibility, best-practices

no

["performance","seo","accessibility","best-practices"]

Lighthouse categories to run

apiKey

string

no

Optional PageSpeed Insights API key; defaults to SEO_MCP_PAGESPEED_KEY

strategy defaults to mobile. All four categories are requested by default. apiKey is optional and overrides SEO_MCP_PAGESPEED_KEY for that call.

seo_audit

Fetches up to 10 MB of HTML with redirects enabled, a 15-second timeout, and an identifying user agent. It extracts title and description lengths, canonical, robots, H1s and heading outline, Open Graph and Twitter tags, JSON-LD types, image alt coverage, internal/external links, word count, language, and viewport. It flags missing or duplicate titles, a missing description, missing or multiple H1s, a missing canonical, and missing or invalid JSON-LD.

{
  "url": "https://www.example.com/landing-page"
}

Parameter

Type

Required

Default

Description

url

string

yes

Public page URL to audit

audit_site

Fetches a sitemap and audits up to 50 of its page URLs with bounded concurrency. Sitemap indexes are supported with a hard cap of five child sitemap fetches. The result includes compact per-page findings, isolated page-fetch errors, a count of each shared issue, and explicit truncation and skipped counts. It does not require Google credentials.

{
  "sitemapUrl": "https://www.example.com/sitemap.xml",
  "maxPages": 20,
  "concurrency": 5
}

Parameter

Type

Required

Default

Description

sitemapUrl

string

yes

Public sitemap URL to audit

maxPages

number

no

20

Maximum pages to audit

concurrency

number

no

5

Maximum page fetches in flight

maxPages defaults to 20 and concurrency defaults to 5. Their maximum values are 50 and 10, respectively.

server_version

Which build of the server is answering, where it is running from, and whether it came out of an npx cache. No credentials.

This tool takes no parameters.

Four values look like this one and are not: what npm calls latest, what the version range resolves to, what the plugin manifest declares, and what is actually running. The first three are all readable and none of them answers the question. Checking the command-line tool is not a substitute either, since it is a separate process resolved separately and can be a different build on the same machine.

The install path is the tell. npx reuses a cached build without re-resolving the range and without erroring, so a server can trail the published release while every other signal reads current; a path under _npx is what shows it.

Call it after updating, before reporting anything. npm view <pkg> version reads a local registry cache and can return the previous version for minutes after a successful publish, while dist-tags and the versions array already carry the new one. Two sessions here independently concluded a publish had failed when it had not, on separate releases. A registry read cannot tell a slow publish from a failed one; asking the running process what it is can.

wporg_plugin

Looks up a WordPress.org plugin by slug and returns active installs, downloads, ratings, support threads, and version dates. It uses the public wp.org API and needs no credentials or API key. A plugin published within the last few days is reported with possiblyLagging: true when a field looks empty, because the wp.org API under-reports fresh plugins; the field may be live on the page already.

{ "slug": "akismet" }

Parameter

Type

Required

Default

Description

slug

string

yes

WordPress.org plugin slug, e.g. akismet

downloadDays

number

no

30

Days of daily download history to fetch; 0 skips it

includeVersionDistribution

boolean

no

true

Also fetch the share of active installs on each plugin version

play_store_stats

Reads the Google Play bulk reports for an app and returns Active Device Installs, plus store-listing visitors and acquisitions grouped by traffic source and search term. hasPlaySearchRows states outright whether any Play search traffic appears, since its absence is a finding rather than an error. Reports lag by days, so lastDatePresent is the last date actually in the files rather than today.

{ "packageName": "com.example.app", "month": "202608" }

Parameter

Type

Required

Default

Description

packageName

string

yes

Android package name, e.g. app.getpsst

month

string

no

Report month as YYYYMM; defaults to the current UTC month. Ignored when startDate and endDate are given

installsDimension

one of overview, country, language, device, os_version, carrier, app_version

no

"overview"

Which installs report to read. overview is undocumented by Google but present in real buckets; the others are the documented breakdowns

include

list of one of ratings, crashes, reviews

no

[]

Extra report families to read. Missing files are normal: Google emits a report only when there is something to report

storePerformanceDimension

one of traffic_source, country

no

"traffic_source"

Which store performance breakdown to read

storePerformanceTotals

boolean

no

false

Read the total_ variant instead. It is a different report, not a rollup of the same one: it carries acquisitions only, with no visitors and no conversion rate, and for some apps it covers far fewer dates and attributes every acquisition to a placeholder source

ratingsDimension

one of country, language, device, os_version, carrier, app_version

no

"country"

Dimension for the ratings report

crashesDimension

one of device, os_version, app_version

no

"app_version"

Dimension for the crashes report

startDate

string

no

Window start in YYYY-MM-DD. With endDate, reads every month the window touches and filters rows to it

endDate

string

no

Window end in YYYY-MM-DD

Set SEO_MCP_PLAY_BUCKET to the reporting bucket (gs://pubsite_prod_... and the bare name both work) and SEO_MCP_PLAY_CREDENTIALS to a service account key with read access to that bucket, falling back to GOOGLE_APPLICATION_CREDENTIALS. Read access to the bucket is a different grant from the Play Console invite play_vitals needs. month defaults to the current UTC month.

app_store_listing

Reads an App Store listing through App Store Connect and measures each locale's fields against Apple's limits: name 30, subtitle 30, keywords 100, promotional text 170. Apple indexes the name, subtitle, and keyword field only, so the description is reported but never scored, and a field one character over its limit is dropped silently rather than rejected, which is why every field is reported against its limit. Promotional text is called out separately because it is the only one of these that can be changed on a live version without a review.

An app can hold a live record and an editable one at the same time, so state selects which is read and the result states the record and version it used. When the record you asked for does not exist, the other one is reported and a note says so rather than passing it off as what you asked for.

The reported state comes from appVersionState, falling back to the deprecated appStoreState. The two spell the same thing differently: a live listing reads READY_FOR_DISTRIBUTION where the deprecated attribute said READY_FOR_SALE. Output captured before and after that change will differ on the string alone, with nothing having happened to the listing.

{ "bundleId": "com.example.app", "state": "live", "platform": "IOS", "storefronts": ["us", "gb"] }

Parameter

Type

Required

Default

Description

appId

string

no

App Store Connect numeric app id; provide this or bundleId

bundleId

string

no

Bundle id, resolved to an app id when appId is not given; provide this or appId

platform

one of IOS, MAC_OS, TV_OS, VISION_OS

no

"IOS"

App Store platform whose version is read

state

one of live, editable

no

"live"

Read the live listing or the editable one being prepared for release

storefronts

list of string

no

["us"]

Storefront country codes for the public ratings lookup

Provide appId or bundleId. Set SEO_MCP_ASC_KEY_PATH to the .p8 private key and SEO_MCP_ASC_KEY_ID to its key id, plus SEO_MCP_ASC_ISSUER_ID for a team key (individual keys have no issuer id). The key and the token it signs never appear in output.

A team key reaches every app on the team, so one key can serve them all. What limits it is the role it was given, and Apple does not let a key's role be changed afterwards: the only edit offered is Revoke. An App Manager key reads listings but not Sales and Trends or analytics reports, so those need a separate key created with Admin, Finance, or Sales and Reports rather than an upgrade of the one you have.

ratings is a list, one entry per requested storefront, not an object keyed by storefront:

{ "ratings": [{ "storefront": "us", "source": "itunes-lookup", "averageUserRating": 4.5, "userRatingCount": 12 }] }

The star rating does not come from App Store Connect. Its API has no aggregate rating resource at all, only age ratings, so the rating is read from the public App Store storefront lookup while every other field on this tool comes from App Store Connect. Two sources reporting one number that looks the same either way, which is why each entry carries source. A rating from a store page and a rating from a private API are not interchangeable and should not be compared as if they were the same measurement.

list_snapshots

Lists the snapshot documents already in the snapshot directory, newest first, with when each was taken, the window it covers, and how many properties, apps, packages and plugins it holds.

{ "limit": 50 }

Parameter

Type

Required

Default

Description

limit

number

no

50

Maximum snapshots to return, newest first

A snapshot pair is worthless if nothing can say which files exist, and every caller was otherwise left keeping its own index of a directory the server owns. A file in the directory that is not a snapshot document is listed with its error rather than hidden, so a name you expect to find never quietly reads as absent. A missing directory is an empty list, not a failure: nothing has been captured yet. total and truncated sit beside the list because the command line prints the structured half alone, where a page cut at limit would otherwise read as the whole history.

snapshot

Captures four surfaces into one timestamped document: Search Console totals and top rows per property, App Store listings, Google Play installs and traffic, and WordPress.org stats. Core Web Vitals field data, Android vitals, App Store sales and App Store reviews are not in it; crux_field_data, play_vitals, app_store_sales and app_store_reviews read those. This is the tool for recording a point in a series, because none of the consoles keep a history you can diff against later.

Search Console totals come from the date dimension, never by summing the query dimension. Google withholds low-volume queries, so a query-level sum undercounts, and that gap reads later as a decline that never happened.

A surface that cannot be read is recorded in place with its error and named in surfacesWithErrors, never omitted, because a surface that silently vanishes reads later as a drop to zero. One slow surface times out without taking the document down.

{
  "properties": ["sc-domain:example.com"],
  "apps": ["1234567890"],
  "packages": ["com.example.app"],
  "slugs": ["akismet"],
  "windowDays": 28,
  "outPath": "2026-09-03.json"
}

Parameter

Type

Required

Default

Description

properties

list of string

no

[]

Search Console properties to capture

apps

list of string

no

[]

App Store apps, each a numeric app id or a bundle id

packages

list of string

no

[]

Google Play package names

slugs

list of string

no

[]

WordPress.org plugin slugs

windowDays

number

no

28

Search Console window in days, ending today

platform

one of IOS, MAC_OS, TV_OS, VISION_OS

no

"IOS"

App Store platform for the app surfaces

storefronts

list of string

no

["us"]

Storefront country codes for App Store ratings

outPath

string

no

File name or path inside the snapshot directory (SEO_MCP_SNAPSHOT_DIR, default ~/.config/seo-mcp/snapshots); must end in .json, or pass auto to name the file after the moment it was taken. An existing file is not overwritten unless overwrite is true

overwrite

boolean

no

false

Replace an existing file at outPath; without it an existing file is left alone and reported

Pass outPath to write the document where compare_snapshots can read it later, or outPath: "auto" to have it named after the moment it was taken (2026-09-04T00-15Z.json), which is what makes an unattended run produce a series rather than one file overwritten forever. It is a file name inside the snapshot directory, SEO_MCP_SNAPSHOT_DIR or ~/.config/seo-mcp/snapshots by default; a path that resolves outside that directory or does not end in .json is refused, and an existing file is left in place and reported unless you pass overwrite: true. A model chooses this string, so the directory is the boundary that keeps a tool call from truncating anything else on the machine. Position and CTR are null rather than 0 when a window has no impressions, so an empty window never compares against real data as a collapse.

compare_snapshots

Reads two snapshot documents and reports what changed between them: clicks, impressions and position per property, page-level and query-level movers above an impressions floor, install and rating deltas, App Store version and locale-count changes, the per-locale name, subtitle, keyword, promotional-text and description lengths plus which fields crossed a character limit, Google Play traffic sources by visitors and acquisitions, and the WordPress.org five-star histogram.

{ "from": "2026-08-06.json", "to": "2026-09-03.json", "minImpressions": 100 }

Parameter

Type

Required

Default

Description

from

string

yes

Snapshot file name or path inside the snapshot directory; latest names the newest snapshot on disk and previous the one before it

to

string

yes

Snapshot file name or path inside the snapshot directory; latest names the newest snapshot on disk and previous the one before it

minImpressions

number

no

100

Ignore page position moves below this many impressions on both sides

from and to resolve inside the same snapshot directory as snapshot's outPath, so this tool reads snapshots and nothing else. Either one also takes latest or previous instead of a file name, which is the comparison almost every caller actually wants and the only one they can ask for without listing the directory first. Both skip a file that will not parse, and asking for previous with a single snapshot on disk says so rather than comparing a document against itself.

It does arithmetic, never judgement. It will not tell you whether a change was good or what caused it, because a diff cannot support that claim. A surface that failed or is missing on either side is marked not comparable and named, so a collection failure is never read as a change, and a file that is not a snapshot document is refused rather than half-parsed.

Snapshots taken before a field was captured still compare. A field one side does not carry comes back as a null delta rather than as a change, and an app pair with no per-locale lengths on either side reports localesComparable: false instead of a listing emptied to zero characters.

app_store_reviews

Reads App Store customer reviews and your responses, filtered by star rating or storefront, following Apple's own paging cursor.

{ "bundleId": "com.example.app", "rating": [1, 2], "territory": "USA", "limit": 100 }

Parameter

Type

Required

Default

Description

appId

string

no

App Store Connect numeric app id; provide this or bundleId

bundleId

string

no

Bundle id; provide this or appId

rating

list of number

no

Only these star ratings

territory

string

no

Only reviews from this storefront

sort

one of -createdDate, createdDate, rating, -rating

no

"-createdDate"

Sort order; newest first by default

limit

number

no

100

Maximum reviews to return across pages

maxPages

number

no

5

Maximum pages to follow

It reports meanOfFetched and histogramOfFetched, never "the rating". Those describe only the reviews this call returned, and a filtered or truncated page would make a mean a different number wearing the same name. App Store Connect exposes no aggregate rating resource at all, which is verifiable in Apple's own OpenAPI specification: every path matching "rating" is an age rating.

app_store_discovery

Reads the App Store surfaces beyond the listing text: search keywords (Apple's actual indexed keyword list, held per locale), app tags, product page optimization experiments, custom product pages, in-app events, territory availability, and review summarizations.

{ "bundleId": "com.example.app", "locales": ["en-US", "ar-SA"], "platform": "IOS" }

Parameter

Type

Required

Default

Description

appId

string

no

App Store Connect numeric app id; provide this or bundleId

bundleId

string

no

Bundle id; provide this or appId

include

list of one of searchKeywords, appTags, experiments, customProductPages, appEvents, availability, reviewSummarizations

no

[]

Which discovery surfaces to read; empty reads all of them

limit

number

no

50

Rows per resource

locales

list of string

no

["en-US"]

Locales for per-locale resources such as searchKeywords

platform

one of IOS, MAC_OS, TV_OS, VISION_OS

no

"IOS"

Platform for resources that require one

includeRows

boolean

no

false

Include every raw row as well as the counts; off by default so a summary call stays small

Each resource carries its own required parameters: searchKeywords needs both a platform and a locale filter, appAvailabilityV2 is a to-one relationship that rejects limit outright. A resource this key or app cannot serve is reported as available: false, never as an empty list, because "no experiments" and "cannot read experiments" are different answers.

crux_field_data

Real-user Core Web Vitals for an origin or a single URL from the Chrome UX Report: the current 28-day field record, with p75s and full histogram bins.

{ "origin": "https://example.com", "formFactor": "PHONE" }

Parameter

Type

Required

Default

Description

origin

string

no

Origin such as https://example.com; aggregates every page under it. Give origin or url, not both

url

string

no

A single page URL. Give origin or url, not both

formFactor

one of PHONE, TABLET, DESKTOP

no

Device class; omit for all form factors combined

metrics

list of string

no

Metric names to request; omit for all available

This is field data, not a lab test; keep pagespeed for Lighthouse audits. Google is discontinuing PageSpeed's own real-world data, so this is where field measurements move. An origin with too few anonymized samples returns hasData: false with a note rather than an error or zeros, since a zeroed LCP would read as a catastrophic regression.

crux_history

The same field metrics as a weekly series, roughly six months of history.

{ "origin": "https://example.com", "formFactor": "PHONE", "collectionPeriodCount": 25 }

Parameter

Type

Required

Default

Description

origin

string

no

Origin such as https://example.com; aggregates every page under it. Give origin or url, not both

url

string

no

A single page URL. Give origin or url, not both

formFactor

one of PHONE, TABLET, DESKTOP

no

Device class; omit for all form factors combined

metrics

list of string

no

Metric names to request; omit for all available

collectionPeriodCount

number

no

Weekly periods to return, 1 to 40. Documented history is about six months; the API decides what it actually has

Each period is a 28-day rolling window stepped weekly, so consecutive points overlap by three weeks and a single week-on-week move is not an independent change. Periods with too few samples keep their place in the series as null rather than being dropped, so the values stay aligned with collectionPeriods.

app_store_sales

Reads App Store Sales and Trends: units downloaded per day, per territory, per app, summarized by SKU.

{ "reportDate": "2026-08-30", "frequency": "DAILY", "reportType": "SALES", "reportSubType": "SUMMARY" }

Parameter

Type

Required

Default

Description

reportDate

string

no

Report date. DAILY and WEEKLY take YYYY-MM-DD (WEEKLY means the week's ending date), MONTHLY takes YYYY-MM, YEARLY takes YYYY. Defaults to the most recent complete period for the frequency

frequency

one of DAILY, WEEKLY, MONTHLY, YEARLY

no

"DAILY"

Report period

reportType

one of SALES, PRE_ORDER, SUBSCRIPTION, SUBSCRIPTION_EVENT, SUBSCRIBER, INSTALLS, FIRST_ANNUAL

no

"SALES"

Sales and Trends report type

reportSubType

one of SUMMARY, DETAILED, SUMMARY_INSTALL_TYPE, SUMMARY_TERRITORY, SUMMARY_CHANNEL

no

"SUMMARY"

Report sub type

version

string

no

Report version, such as 1_0 or 1_3, when the default is not accepted

includeRows

boolean

no

false

Include every raw report row as well as the per-SKU summary

Set SEO_MCP_ASC_VENDOR_NUMBER; App Store Connect shows the vendor number under Payments and Financial Reports, beside the legal entity name. Sales and Trends needs a team key with the Admin, Finance, or Sales and Reports role. Daily reports land the next day, so the default report date is two days back rather than today. reportDate takes the shape its frequency needs: YYYY-MM-DD for DAILY and for WEEKLY, where it means the week's ending Sunday, YYYY-MM for MONTHLY, and YYYY for YEARLY; leave it out and each frequency defaults to its most recent complete period.

A period with no sales returns hasData: false with a note, not an error, because a quiet day should not look like a broken integration. Units come from the Sales and Trends pipeline, which is separate from App Analytics and can disagree with it.

play_vitals

Reads Android vitals from the Play Developer Reporting API: crash rate, ANR rate, error counts and startup metrics, daily or hourly, with optional breakdowns such as versionCode or countryCode.

{ "packageName": "com.example.app", "metricSets": ["crashRate", "anrRate"], "days": 28 }

Parameter

Type

Required

Default

Description

packageName

string

yes

Android package name

metricSets

list of one of crashRate, anrRate, errorCount, slowStartRate, excessiveWakeupRate

no

["crashRate","anrRate"]

Which Android vitals metric sets to query

aggregationPeriod

one of DAILY, HOURLY

no

"DAILY"

DAILY is reported in America/Los_Angeles, HOURLY in UTC

days

number

no

28

How many days back to query

dimensions

list of string

no

[]

Breakdown dimensions such as versionCode or countryCode

pageSize

number

no

1000

Rows per metric set

includeRows

boolean

no

false

Include every raw row as well as the counts; off by default so a summary call stays small

Set SEO_MCP_PLAY_CREDENTIALS to the service account key, falling back to GOOGLE_APPLICATION_CREDENTIALS. The account also has to be invited in Play Console under Users and permissions with the permission to view app information and app quality. The token is minted for the playdeveloperreporting scope, which is a separate grant from the Cloud Storage read play_store_stats needs. One account can hold both, but a key that only has the bucket grant gets a 403 here.

The window is clamped to the freshness the API reports for itself, since it refuses an end date past that and asking through today always fails. The result says how current the data actually is, so zero rows through a known date is distinguishable from zero rows because the day has not landed. This API carries no acquisition or conversion data; play_store_stats has that.

Google Ads

Reads the account through the API rather than the console. A console table pages, so a count taken from the first screen can be wrong without looking wrong: one keyword count was read as two when the answer was five, because the table shows ten rows and there were fourteen. These tools return every row.

Set GOOGLE_ADS_DEVELOPER_TOKEN, GOOGLE_ADS_CLIENT_ID, GOOGLE_ADS_CLIENT_SECRET, GOOGLE_ADS_REFRESH_TOKEN and GOOGLE_ADS_CUSTOMER_ID (dashes optional). Two conveniences: GOOGLE_ADS_CLIENT_SECRET_PATH reads the client id and secret out of the OAuth client JSON that Google Cloud gives you, and GOOGLE_ADS_ENV_FILE points at an existing .env-shaped file holding any of these, so a refresh token that already lives somewhere is read in place rather than copied. The process environment wins over the file. GOOGLE_ADS_API_VERSION overrides the API version.

ads_campaigns

Campaign name, status, daily budget, impressions, clicks, cost and conversions over a window.

{ "days": 30 }

Parameter

Type

Required

Default

Description

days

number

no

30

How many days back to report, ending today

ads_keywords

Every keyword with its state, effective CPC bid, approval status, serving status and metrics.

ELIGIBLE does not mean serving. It means approved and capable of serving, and a paused keyword reports it. That is why status is returned alongside it: without it a paused keyword's row is identical to a live one, and someone who has just paused three keywords reads that as the pause not having taken. Paused keywords are named in a note rather than dropped, because silently removing rows is the same failure one layer down: you ask whether a keyword is in the account and get nothing back. Pass status to filter deliberately.

{ "days": 30 }

Parameter

Type

Required

Default

Description

days

number

no

30

How many days back to report, ending today

status

one of ENABLED, PAUSED, REMOVED

no

Limit to one keyword state. Omitted, every keyword is returned with its state named, because dropping rows silently is how a count taken from this tool goes wrong the way a console count does

ads_ads

Every ad with its ad strength, policy approval status, serving status and metrics.

{ "days": 30 }

Parameter

Type

Required

Default

Description

days

number

no

30

How many days back to report, ending today

ads_ad_copy

Reads what an ad actually says. ads_ads gives the id, strength, approval and status; this gives the text, which is the thing every creative question needs and the reason that question otherwise ends in the browser.

{ "adGroup": "brand-exact" }

Parameter

Type

Required

Default

Description

adGroup

string

no

Limit to one ad group by name. Omitted, every ad in the account is read, which is what answers whether a headline is repeated across ad groups

adId

string

no

Limit to one ad by its numeric id, for reading back the copy that was supposed to ship

includeRemoved

boolean

no

false

Include removed ads. Off by default: a removed ad's copy is history, and it crowds out the ads that are serving

Every headline and description comes back with its pinning and Google's own performance label, plus the display path, the final URLs, and the policy topics behind a limited or disapproved status. The approval word says something is wrong; the topic says what. APPROVED_LIMITED beside TRADEMARKS_IN_AD_TEXT is a fix; APPROVED_LIMITED on its own is a trip to the console.

It also answers the two questions a per-ad view cannot:

  • Why is strength Poor. The count against what Google wants, 3 of 15 headlines, 2 of 4 descriptions, and how many assets are pinned. Pinning is usually deliberate, usually invisible in the strength word, and a common reason strength reads lower than the copy deserves. Text repeated inside one ad is named too, since a repeated asset takes a slot without adding a variation.

  • Is a headline duplicated across ads. Headline text appearing in more than one ad is listed with the ads and ad groups carrying it. Two ads in one ad group that share their headlines are not two variants being tested against each other, and nothing in the console says so at a glance.

Removed ads are excluded unless includeRemoved is set, and only a responsive search ad carries text in these fields: any other ad type is listed with its type and no copy, rather than as an ad with nothing to say. Assets attached to the ad, campaign or account, such as sitelinks, promotions and prices, are not read here, so an ad that looks thin in this output may still be serving with assets alongside it.

ads_assets

What is attached under the ad: sitelinks, callouts, structured snippets, promotions, prices, call and image assets, at all three levels, with what each one actually says rather than only its type and id.

{ "campaign": "search-uk-us-2026-09" }

Parameter

Type

Required

Default

Description

campaign

string

no

Limit campaign and ad group assets to one campaign by name. Account-level assets are still listed, because they apply to every campaign including this one

type

one of SITELINK, CALLOUT, STRUCTURED_SNIPPET, PROMOTION, PRICE, CALL, IMAGE

no

Limit to one asset type. Omitted, every type is listed, including types this tool has no shaped reading for

includeRemoved

boolean

no

false

Include links whose status is removed. Off by default: a removed asset is history and crowds out the ones that can serve

A promotion reads back as up to 20% off on Pro plan with code LAUNCH20, 2026-01-01 to 2026-01-31, not as PROMOTION #4417. That matters because Google states a promotion's percentage in millionths, where 1,000,000 is 100%, so the raw field is a number nobody would recognise as a discount. Prices come back with their offerings and currency, sitelinks with their descriptions.

Three things worth knowing before reading a result:

  • An account-level asset applies to every campaign, so it is listed even when you name one campaign. This is the other half of ads_ad_copy: an ad that looks bare there may be serving with four sitelinks and a promotion beside it, none of which are attached to its campaign.

  • Attached is not shown. Google decides per auction whether to show an asset and which ones. This says what is available to serve, not what served.

  • A campaign name that matches nothing is refused, not answered. A typo used to come back as zero rows with no error, next to a note explaining that account-level assets are listed too, so the reader concluded the account had none. The name is resolved before anything is read, and an unknown one says so. The caller who mistypes a campaign is exactly the caller who then says "that campaign has no sitelinks" and acts on it.

  • A level that cannot be read is reported as an error in place. The three levels are three separate queries, and if one fails the other two still come back with levelErrors naming the one that did not. An empty list that quietly meant "the query broke" would read as "nothing attached", which is the wrong answer to the only question this tool gets asked.

A type this tool has no shaped reading for is named with its asset type and its field type and left at that, rather than given an invented summary: a TEXT asset filed as BUSINESS_NAME is mostly described by the second half. The field type is shown only where it differs from the asset type, since the two are usually the same word and repeating it is noise. Asset metrics are not reported here.

ads_query

An arbitrary GAQL SELECT for a question the shaped reads do not cover. GAQL has no statement other than SELECT, so this cannot change anything, and a query that does not start with SELECT is refused.

{ "query": "SELECT campaign.name, metrics.cost_micros FROM campaign WHERE segments.date DURING LAST_7_DAYS" }

Parameter

Type

Required

Default

Description

query

string

yes

A GAQL SELECT statement. GAQL has no other statement, so this cannot change anything

ads_search_terms

The queries that actually triggered an ad, with the keyword each one matched. This is the paid equivalent of the Search Console query dimension, and it carries the same caveat: Google withholds terms too few people searched, so a term that is not listed is unknown rather than absent.

{ "days": 90, "minImpressions": 1 }

Parameter

Type

Required

Default

Description

days

number

no

30

How many days back to report, ending today

minCost

number

no

0

Drop search terms that cost less than this over the window

minImpressions

number

no

0

Drop search terms below this many impressions

zeroConversionsOnly

boolean

no

false

Keep only terms that converted nothing, which is the list that feeds negative keywords

ads_changes

What changed in the account, when, which fields, by whom, and whether it came from a tool or from someone in the browser: client is GOOGLE_ADS_API for the former and GOOGLE_ADS_WEB_CLIENT for the latter. This is the audit trail for anything ads_update writes, and for console edits made by hand. Google keeps 30 days, so a longer window is refused rather than silently truncated.

{ "days": 14, "limit": 100 }

Parameter

Type

Required

Default

Description

days

number

no

14

How many days of change history to read, ending now. Google keeps 30 days and refuses more

limit

number

no

100

Most recent changes to return

ads_negatives

The negative keywords already in place, at campaign, ad group or shared-set level. A negative blocks traffic without leaving any record that it did, so this is the list to check when a keyword stops serving and nothing looks wrong, and before adding a term that may already be there.

{ "level": "all" }

Parameter

Type

Required

Default

Description

level

one of campaign, adGroup, sharedSet, all

no

"all"

Which negatives to read. A term blocked at campaign level is blocked everywhere in it; a shared set applies to every campaign it is attached to

ads_negatives_update

Adds or removes negative keywords in a batch, enumerated one by one. There is no pattern or match-all form on purpose: "block every term matching X" is one typo away from an account-sized mistake, and an explicit list cannot make that mistake.

{ "action": "add", "level": "campaign", "target": "search-uk-us", "keywords": ["free", "crack"], "matchType": "EXACT", "dryRun": false }

Parameter

Type

Required

Default

Description

action

one of add, remove

yes

Add negative keywords or remove existing ones. Removal matters as much as adding: a wrong negative shows up as nothing at all

level

one of campaign, adGroup

no

"campaign"

Where the negatives live. A campaign-level negative blocks the term everywhere in that campaign

target

string

yes

The campaign or ad group name. It must match exactly one or nothing is changed

keywords

list of string

yes

The negative terms, enumerated one by one. There is no pattern or match-all form: a selector is one typo away from blocking a whole campaign

matchType

one of BROAD, PHRASE, EXACT

no

"EXACT"

How each term blocks. BROAD blocks any query containing all its words, which is the setting that can silently kill a campaign

dryRun

boolean

no

true

Report what would change, and which proposed negatives would block a live keyword, without changing anything

confirm

boolean

no

false

Perform the batch even though a guard tripped. The dry run lists what tripped, so this confirms something already read

Negatives feel safe because they only reduce spend, and that instinct is what makes them dangerous. A wrong bid shows up as spend. A wrong negative shows up as nothing: the traffic stops arriving, the term leaves the search terms report, and no row anywhere says why. Adding backup as a broad negative to a backup-plugin campaign ends its traffic, and Google reports no error because it is a perfectly valid negative.

So before adding anything, every proposed negative is checked against the campaign's own live keywords, and the batch is refused unless confirm is set. The refusal names what it would have cost: "backup" as a BROAD negative would block this campaign's own keyword "wordpress backup", which served 41 impressions. The check mirrors Google's matching closely but Google is the authority, and it is deliberately generous, because a false warning costs a sentence and a missed one costs the campaign.

Removals are not collision-checked. Removing a negative can only let traffic through, which shows up as spend rather than as silence.

ads_update

Changes one keyword bid, campaign daily budget, campaign status, ad status or keyword status. This is the only tool here that spends money, so it is built to be hard to fire by accident.

Pausing a keyword is its own kind, because dropping its bid is not the same thing. A keyword with a lowered bid is still enabled, still eligible, and still competing for the same daily budget. If the reason to act was that budget is the constraint, lowering the bid does not free any of it.

{ "kind": "budget", "target": "search-uk-us-2026-09", "value": "5.00", "dryRun": false, "confirm": true }

Parameter

Type

Required

Default

Description

kind

one of bid, budget, campaignStatus, adStatus, keywordStatus

yes

What to change: a keyword's max CPC bid, a campaign's daily budget, a campaign's status, an ad's status, or a keyword's status. Use keywordStatus to stop one keyword serving; dropping its bid is not the same thing, because the keyword stays eligible and keeps competing for the same budget

target

string

yes

The keyword text, the campaign name, or the numeric ad id. It must match exactly one thing or the call is refused

value

string

yes

The new amount in dollars for a bid or budget, or pause or enable for a status

dryRun

boolean

no

true

Report what would change and which guards it trips, without changing anything. On by default: this tool spends money, so performing a change has to be asked for

confirm

boolean

no

false

Perform a change that trips a guard. Ignored on a dry run. The dry run lists the guard reasons, so this confirms something already read rather than something unseen

Four rails, each from a real failure rather than a hypothetical:

  • A dry run by default. dryRun defaults to true, so omitting it reports the change and stops. A required parameter enforces this better than a command-line flag, because a flag can be forgotten and a default cannot.

  • Exactly one match or refuse. A target that matches nothing is a typo; a target that matches two is a request to change something you did not name. Both stop before any write.

  • Guards with reasons, in words. More than three times the current amount, more than $25 on a single bid or daily budget, or pausing something that is currently serving. A budget change also states the monthly equivalent, because $30 a day reads small and is about $912 a month. The dry run lists the reasons, and confirm then confirms something you have read rather than something unseen.

  • The value is read back after the write. An HTTP 200 means the request was accepted, not that it stored what you meant. The result carries readBack and matches, and a mismatch is returned as an error.

A change that would be a no-op says so instead of sending a pointless mutation.

From the command line this tool needs --allow-spend as well as --allow-write. One flag authorising both "resubmit a sitemap" and "triple a daily budget" is not a gate.

ads_keyword_create

Adds one keyword to an ad group. The only tool here that creates rather than changes, and it is guarded differently for that reason.

{ "keyword": "wordpress backup plugin", "adGroup": "brand-exact", "bid": 1.2, "dryRun": false }

Parameter

Type

Required

Default

Description

keyword

string

yes

The keyword text to add. It is created as written; this tool does not guess at variants

adGroup

string

yes

The ad group to add it to. It must match exactly one or nothing is added

bid

number

yes

The max CPC bid in dollars. There is no current bid to compare against on a create, so the only size check is the ceiling

matchType

one of EXACT, PHRASE, BROAD

no

"EXACT"

How the keyword matches. EXACT by default because it is the one that buys what it says; PHRASE and BROAD buy more than the text written here and each trips a guard

dryRun

boolean

no

true

Report what would be added and which guards it trips, without adding anything

confirm

boolean

no

false

Add it even though a guard tripped. The dry run lists every reason, so this confirms something already read

Every other write in this package reads a current value, compares it to the one asked for, and refuses when they already match. A create has no current value. There is nothing to compare and nothing to refuse against, so the comparison has to be replaced rather than skipped, and what replaces it is a duplicate check:

  • A keyword already in the target ad group is refused, including a removed one. A removed criterion still holds the text, and Google rejects the duplicate with an error naming a resource the interface does not show, which is a confusing thing to meet without warning.

  • A copy elsewhere in the account trips a guard rather than refusing. Running the same text in two ad groups can be deliberate, so refusing would make a legitimate structure impossible; saying nothing would let two copies compete for one budget silently.

  • EXACT by default. PHRASE and BROAD each buy more than the text written here, so each trips a guard. Broad is the match type that spends on searches nobody meant to buy.

  • The keyword is read back after the write, and its match type and status are compared to what was sent. A 200 on a create means accepted, not present-and-correct.

One asymmetry worth stating plainly: a created keyword starts serving immediately, and unlike a bid change there is no previous state to return to. Undoing it means pausing or removing what was made.

ads_update_batch

Changes several keyword bids, or several campaign daily budgets, in one call. One kind per call: a total across bids and budgets would add a per-click ceiling to a per-day amount, and no honest sentence describes that sum.

{ "kind": "bid", "changes": [{ "target": "wordpress backup", "value": 0.85 }, { "target": "backup plugin", "value": 0.6 }], "dryRun": false, "confirm": true }

Parameter

Type

Required

Default

Description

kind

one of bid, budget

yes

One kind per call. A summed guard is only honest inside one kind: bids and budgets sum to dollars, statuses do not, and mixing them makes the total unreadable

changes

JSON list

yes

A named list of pairs, each with its own value. There is no selector form: enumeration cannot make the mistake that a pattern can

dryRun

boolean

no

true

Resolve and price every entry and report the total, without changing anything

confirm

boolean

no

false

Perform the batch even though a guard tripped. The dry run lists every reason, so this confirms something already read

It is a named list of pairs, not a rule applied to many things. There is no "raise everything by 20%" and no selector, because the mistake this tool exists to prevent is exactly the one a selector makes easy: a pattern that matches more than the caller pictured, applied before anyone can see the list it produced. Every entry names one target and the value it should end at, and the dry run prints that list back.

Four things it does that ads_update called in a loop does not:

  • Everything resolves before anything is written. If entry four matches nothing, entries one to three are not already live. A loop of single calls fails halfway and leaves the account in a state nobody chose, with no single row anywhere saying so.

  • The sum is guarded, not only each entry. Five raises that are each within the per-item ceilings are still one large spend change together, and doing them one at a time is how that goes unnoticed.

  • The one entry out of line with the rest is named. Nineteen bids moving a few cents and one moving $40 can sit under every ceiling and still be the mistake. An entry whose move is far larger than the middle of the batch is flagged by name, because a typo hides inside an acceptable total, and that is exactly how a batch differs from the same writes sent one at a time.

  • Two entries cannot name the same thing. The same target twice is refused, and so are two differently named campaigns that share one budget, where the total would count it twice and the second write would quietly win.

The per-entry ceilings stay flat however long the list is, because the per-entry question is whether that one entry is a typo and a typo does not get more acceptable in a bigger batch. The ceiling on the batch total grows with the batch, slowly: twenty entries is not twenty times the risk of one, it is one decision taken once. A guard that trips on every realistic batch is not a guard, it is a checkbox, and once confirm is routine it gets passed unread.

The total is always stated in words whether or not anything tripped, since the sentence is what gets read and the guard is only what stops you when it does not. For budgets that is the monthly figure both ways: These daily budgets come to $13.00 a day, about $395 a month, up from $10.00 a day, about $304 a month.

Every value is read back after the write, entry by entry. The result names which entries did not store what was sent first, then which are live with what the account now holds, because on a partial landing the question is never how many but which ones. One accepted request is one acceptance, not N stored values, and a batch is exactly where a partial landing hides. The batch is sent as a single request without partial failure, so a rejected write leaves nothing behind, and the error says so rather than leaving you to guess.

Like ads_update, it needs --allow-spend as well as --allow-write from the command line.

Running a tool from the command line

Every tool above is also runnable without an MCP client, which is what to use when a result has to land in a file that a later run can diff:

seo-mcp query search_analytics --site-url sc-domain:example.com --start-date 2026-08-05 --out /tmp/sa.json
seo-mcp query --help                  # list the tools
seo-mcp query wporg_plugin --help     # list one tool's parameters

Every run names its own version on stderr (seo-console-mcp 0.15.1 running wporg_plugin), so stdout stays parseable and an --out file stays pure JSON. A result does not otherwise say which binary produced it, and that is not academic: npx will reuse a cached older build with no error at all, and a failed install leaves the previous version in place and working. What is running, what the version range resolves to, and what npm calls latest are three values that usually agree and independently do not have to.

Flags are the tool's parameter names in kebab-case (--site-url for siteUrl); the camelCase spelling works too. List values are comma-separated. The result is written to --out, or to stdout when it is omitted, and a failure exits non-zero with the message on stderr. It runs the same implementation the MCP surface exposes, so the two cannot drift.

Tools that change data (submit_sitemap, delete_sitemap, request_recrawl, indexnow_submit) are marked (write) in the listing and refuse to run from the command line unless --allow-write is passed.

A history is one cron line away, and the server deliberately does not own a scheduler: your machine already has one that survives a restart.

# every Monday at 06:00, one snapshot named after the moment it was taken
0 6 * * 1 seo-mcp query snapshot --properties sc-domain:example.com --out-path auto

Development

npm run dev
npm run build
npm test
npm run lint
npm run format
npm run format:check
npx tsc --noEmit

Tests use injected fake Google clients and never call live Google services. Do not commit service account keys. In addition to *.key.json, this repository ignores credentials*.json, .env*, PEM files, and P12 files.

Available Tools

43 tools
ads_ad_copyA

Read what a Google Ads ad actually says: every headline and description with its pinning and Google's performance label, the display path, the final URLs, and the policy topics behind a limited or disapproved status rather than only the status word. Also reports headline text shared by more than one ad, since two ads in an ad group with the same headlines are not testing anything against each other. Assets such as sitelinks and promotions are not read here; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
adIdNoLimit to one ad by its numeric id, for reading back the copy that was supposed to ship
adGroupNoLimit to one ad group by name. Omitted, every ad in the account is read, which is what answers whether a headline is repeated across ad groups
includeRemovedNoInclude removed ads. Off by default: a removed ad's copy is history, and it crowds out the ads that are serving

Output Schema

ParametersJSON Schema
NameRequiredDescription
adsYes
notesYes
rowCountYes
duplicateHeadlinesYesHeadline text appearing in more than one ad, with the ads carrying it. Two ads in one ad group sharing headlines test nothing against each other

TDQS

A4.1/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden. It explicitly declares the operation is read-only and states what it does and does not read. It also explains that it reports the actual policy topics behind limited/disapproved statuses, going beyond the status word. While it doesn't mention potential pagination or performance limits, the description is transparent about its core behavior and limitations.

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 about 60 words and packs every sentence with distinct value: the first explains the core read scope, the second addresses duplicate headlines, and the third clarifies exclusions and read-only nature. It is efficient and front-loaded, though slightly dense. No filler or tautology.

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?

The tool has an output schema, so return values are already structured. The description covers the essential info an agent needs: what is read, what is excluded, and the read-only nature. It could mention edge cases like pagination or how omitted filters behave, but the schema covers parameter behavior. Overall it is sufficiently complete for a read tool with a rich output schema.

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 each parameter (adId, adGroup, includeRemoved) already has a clear description. The tool description itself adds no parameter-specific meaning—the details about 'for reading back the copy' and 'answers whether a headline is repeated across ad groups' appear in the schema, not the description. Per the rubric, high schema coverage sets a baseline of 3, and the description does not exceed it.

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 opens with a clear verb ('Read') and a specific resource ('what a Google Ads ad actually says'), then enumerates exactly which details it covers (headlines, descriptions, pinning, performance labels, URLs, policy topics). It also explicitly states what it does NOT read (assets like sitelinks), which distinguishes it from the sibling ads_assets. This gives an agent a precise, unambiguous picture of the tool's scope.

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?

The description provides contextual guidance: it notes that duplicate headlines are reported because they indicate poor A/B testing, and it clarifies that assets are not covered (implying use ads_assets for those). It also labels itself 'read-only', steering away from update tools. However, it does not explicitly name alternative tools such as ads_ads or ads_assets, so an agent would need to infer the comparison from the sibling list rather than being directly told when to use each.

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

ads_adsA

Read Google Ads ads with ad strength, policy approval status, serving status and metrics; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoHow many days back to report, ending today

Output Schema

ParametersJSON Schema
NameRequiredDescription
adsYes
daysYes
notesYes
rowCountYes

TDQS

A4/5.0
Behavior3/5

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

With no annotations provided, the description carries the burden of behavioral disclosure. It states 'read-only', making clear it has no mutation effects. It also lists the types of data returned, but does not explain what happens if no ad data exists, whether authentication is required, or any pagination limits. This is adequate for a simple read tool but lacks depth.

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 a single, efficient sentence that front-loads the action and read-only nature, then lists the specific fields returned. There is no wasted wording, and it conveys the core purpose succinctly.

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?

Given a simple one-parameter tool with an existing output schema, the description adequately covers what data the tool retrieves and its read-only nature. It could mention the default date range or clarify that it returns a list of ads, but these are minor gaps given the schema covers the parameter details and the output schema handles return structure.

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?

The input schema fully documents the 'days' parameter with a clear description of its purpose and constraints. The tool description does not mention the parameter at all, but since schema coverage is 100%, the baseline of 3 applies without any additional semantic value added.

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 clearly states the verb ('Read'), the resource ('Google Ads ads'), and the specific data points ('ad strength, policy approval status, serving status and metrics'). It explicitly marks the operation as read-only and distinguishes itself from sibling tools like ads_campaigns and ads_keywords by focusing on the ad level with these specific attributes.

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?

The description implies that this tool is for retrieving ad-level details with the listed fields, which differentiates it from sibling tools. However, it does not explicitly state when to prefer this over others or provide exclusions, though the specific fields give clear context for its intended use.

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

ads_assetsA

Read the sitelinks, callouts, structured snippets, promotions, prices, call and image assets attached to the account, its campaigns and its ad groups, with what each one actually says rather than only its type and id. An account-level asset applies to every campaign, so it is listed even when one campaign is named: an ad that looks bare in ads_ad_copy may be serving with these beside it. Attached is not shown, and a level that cannot be read is reported as an error in place rather than as nothing attached; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
typeNoLimit to one asset type. Omitted, every type is listed, including types this tool has no shaped reading for
campaignNoLimit campaign and ad group assets to one campaign by name. Account-level assets are still listed, because they apply to every campaign including this one
includeRemovedNoInclude links whose status is removed. Off by default: a removed asset is history and crowds out the ones that can serve

Output Schema

ParametersJSON Schema
NameRequiredDescription
notesYes
assetsYes
byTypeYesHow many of each type were found, so an absent type is visible as absent
rowCountYes
levelErrorsYesA level that could not be read is recorded here rather than omitted, so an empty list is never mistaken for nothing attached

TDQS

A4.8/5.0
Behavior5/5

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

With no annotations provided, the description carries full responsibility for behavioral disclosure. It explicitly notes the tool is read-only, that account-level assets are included even when a campaign is specified, that 'Attached is not shown', and that unreadable levels are reported as errors. These disclosures go well beyond typical descriptions and cover key behavioral nuances.

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 three well-crafted sentences, with the primary purpose front-loaded. Each sentence adds distinct value: the main read operation, the account-level nuance with a practical example, and behavioral caveats plus the read-only note. There is no redundant or filler text.

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?

Given the tool's complexity (multiple asset types, multiple levels, filtering) and the presence of an output schema (which covers return values), the description is complete. It explains filtering behavior, error handling, and the relationship to ad copy, giving an agent everything needed to call it correctly without requiring external knowledge.

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

Parameters5/5

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

Although the schema already documents all parameters (100% coverage), the description adds significant semantic value. For 'type', it notes that omitting it lists all types including those without shaped readings; for 'campaign', it clarifies that account-level assets are still listed; for 'includeRemoved', it explains the rationale for the default. This enriches each parameter's meaning beyond the basic schema text.

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 ('Read') with a clear resource ('sitelinks, callouts, structured snippets, promotions, prices, call and image assets') and scope ('account, campaigns, ad groups'). It further specifies that it returns actual content rather than just type/id, which distinguishes it from sibling tools like ads_ad_copy. This is a precise, non-tautological purpose.

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?

The description provides clear context on when to use this tool, notably the example that an ad looking bare in ads_ad_copy may be serving with assets from this tool. It implicitly differentiates from ads_ad_copy by emphasizing asset content. However, it does not explicitly name alternatives or state when not to use this tool, so it falls 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.

ads_campaignsA

Read Google Ads campaigns: status, daily budget, impressions, clicks, cost and conversions over a window. Needs GOOGLE_ADS_DEVELOPER_TOKEN, an OAuth client and a refresh token; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoHow many days back to report, ending today

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
notesYes
rowCountYes
campaignsYes

TDQS

A4.3/5.0
Behavior4/5

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

No annotations are present, so the description carries the burden. It explicitly discloses read-only behavior and the required credentials (developer token, OAuth client, refresh token), which are the key behavioral and operational facts. It does not discuss pagination or rate limits, but these are not necessary for a simple read with an output 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?

A single sentence that packs the resource, metrics, time scope, and auth requirements with no filler. Essential information is front-loaded.

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 one-parameter read-only tool with a full output schema, the description plus schema cover the operation, auth, safety profile, and parameter semantics. Nothing an agent needs to invoke it correctly 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?

The only parameter, days, is already fully described in the schema (default, min, max, meaning). The description's 'over a window' adds no new semantic detail, so with 100% schema coverage the baseline 3 is 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?

States a specific verb ('Read'), a specific resource ('Google Ads campaigns'), and enumerates the exact metrics returned (status, daily budget, impressions, clicks, cost, conversions) over a time window. This clearly distinguishes it from sibling ads_* tools that target keywords, ads, ad copy, or assets.

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?

Provides clear context: this is the tool for campaign-level Google Ads performance data over a window, and it lists the required auth setup. However, it does not explicitly name alternatives or state when not to use it, so it stops short of full routing guidance.

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

ads_changesA

Read the Google Ads change history: what changed, when, which fields, by whom, and whether it came from a tool or from someone in the browser. Google keeps 30 days and at most 10,000 rows, so an empty result over a longer window is a limit rather than a finding. Filter on resourceType rather than on changed field names: a budget change reports amountMicros and says neither budget nor status. This is the audit trail for anything ads_update writes; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoHow many days of change history to read, ending now. Google keeps 30 days and refuses more
limitNoMost recent changes to return

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
notesYes
changesYes
rowCountYes

TDQS

A4.7/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden, and it delivers: it declares read-only, states Google's 30-day and 10,000-row retention limits, and warns that empty results over longer windows are limits rather than findings. It also discloses the filtering quirk about resourceType vs. changed field names, which an agent could not infer from the schema alone.

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?

Three sentences, each earning its place: purpose and content, retention-limit caveat, and filtering guidance. The most important information is front-loaded, and the read-only note closes it without redundancy.

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 tool with two self-describing parameters and an output schema, the description covers purpose, scope, behavioral limits, filtering semantics, and sibling relationship. Nothing an agent needs in order to decide when and how to call this tool 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?

The input schema already describes both parameters with 100% coverage, so the baseline is 3. The description adds meaningful value beyond the schema by explaining how the days parameter interacts with Google's retention limit and by clarifying the correct filtering approach (resourceType, not changed field names) even though those details are not directly schema properties.

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 opens with a specific verb and resource ('Read the Google Ads change history') and details what the history contains: what changed, when, fields, by whom, and source. It distinguishes itself from sibling data tools by explicitly positioning itself as the audit trail for ads_update writes, so an agent can tell it apart from ads_campaigns or ads_keywords.

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?

The description makes the intended use clear: consult this tool when you need the change/audit history rather than the current state, and it explicitly notes it is the audit trail for anything ads_update writes. It gives practical guidance on interpreting empty results over long windows and how to filter. It does not explicitly name alternatives to use instead for current data, but the context is clear enough.

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

ads_keyword_createA

Add one keyword to an ad group. This is the only tool here that creates rather than changes, and it is guarded differently for that reason: there is no current value to compare against, so it is a duplicate check instead. It refuses a keyword that already exists in the target ad group, including a removed one, since a removed criterion still holds the text and Google rejects the create with an error naming a resource the interface does not show. A copy elsewhere in the account trips a guard rather than refusing, because two copies compete for the same budget. EXACT by default; PHRASE and BROAD buy more than the text written and each trips a guard. Dry run unless dryRun is false, and the keyword is read back afterwards

ParametersJSON Schema
NameRequiredDescriptionDefault
bidYesThe max CPC bid in dollars. There is no current bid to compare against on a create, so the only size check is the ceiling
dryRunNoReport what would be added and which guards it trips, without adding anything
adGroupYesThe ad group to add it to. It must match exactly one or nothing is added
confirmNoAdd it even though a guard tripped. The dry run lists every reason, so this confirms something already read
keywordYesThe keyword text to add. It is created as written; this tool does not guess at variants
matchTypeNoHow the keyword matches. EXACT by default because it is the one that buys what it says; PHRASE and BROAD buy more than the text written here and each trips a guardEXACT

Output Schema

ParametersJSON Schema
NameRequiredDescription
bidYes
notesYes
guardsYesA create is guarded by a duplicate check rather than a before-and-after comparison, because there is no before
adGroupYes
appliedYes
keywordYes
matchesYes
campaignYes
readBackYesThe keyword as the account holds it after the write. Null when it could not be read back, which is not the same as not created
matchTypeYes
customerIdYes

TDQS

A4.9/5.0
Behavior5/5

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

No annotations are provided, so the description carries the full burden. It discloses several behavioral traits: duplicate checking (including removed keywords), account-copy guard, match-type consequences (EXACT vs PHRASE/BROAD buying more), default dry-run behavior, and read-back after creation. These are significant operational details beyond what the schema reveals (e.g., dryRun default). No contradictions with annotations since none are present.

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 compact yet dense, with every sentence contributing new operational insight. It front-loads the core action, then layers guard logic and defaults. No fluff or repetition; a model agent can quickly grasp the essential behavior and the reasons behind it. The multi-sentence structure is justified by the complexity of the tool's safeguards.

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?

Given the tool's complexity (6 parameters, guard mechanisms, dry-run semantics), the description covers all necessary details: what happens on create, how duplicates and copies are handled, match-type trade-offs, dry-run default, confirmation requirement, and post-readback. The output schema is present, so return format is documented elsewhere. No major gaps remain for an agent to invoke 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?

Schema coverage is 100% meaning all six parameters have descriptions. However, the description adds context beyond the schema: it explains the guard logic for duplicate keywords (relates to 'keyword' and 'adGroup'), the reason EXACT is default, and the implications of matchType. It also clarifies the bid ceiling check rationale. While the schema already documents parameters, the description enriches the semantics, especially for behaviorally relevant fields like dryRun and confirm. Slight deduct for not adding explanation to the existing param descriptions, but the integration is strong.

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 leads with a clear, specific verb and resource: 'Add one keyword to an ad group.' It immediately differentiates this tool from siblings by stating it is 'the only tool here that creates rather than changes,' which disambiguates it from ads_update and ads_negatives_update. The phrase 'guarded differently' further signals unique behavior.

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?

The description explicitly says when to use this tool ('Add one keyword') and contrasts it with other tools ('only tool here that creates rather than changes'). It also explains when not to use it indirectly: the duplicate and copy guards define constraints on when the tool will succeed. The dry-run behavior and confirm parameter provide a clear usage workflow, effectively guiding when to invoke with dryRun=false.

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

ads_keywordsA

Read every Google Ads keyword with its effective CPC bid, approval and serving status, and metrics. Returns every row rather than a first page, which is how a count taken from the console goes wrong; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoHow many days back to report, ending today
statusNoLimit to one keyword state. Omitted, every keyword is returned with its state named, because dropping rows silently is how a count taken from this tool goes wrong the way a console count does

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
notesYes
keywordsYes
rowCountYes

TDQS

A4/5.0
Behavior4/5

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

With no annotations present, the description carries the full behavioral burden and does well: it explicitly declares 'read-only' and discloses the non-paginated 'returns every row' behavior. It also hints at why counts from this tool differ from console counts, which is useful operational context. It stops short of discussing auth needs or rate limits, but those are not critical for this read-oriented tool.

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 sentence-length clauses with zero filler: the first states the resource and fields, the second explains the key behavioral difference from a console count. The 'read-only' safety hint is included without extra wording.

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?

Given the presence of an output schema, two optional parameters, and a clear behavioral description, the tool definition is nearly complete. It explains return scale, read-only nature, and the status-omission behavior via schema. The only gap is the lack of explicit sibling routing, which is already penalized under usage guidelines.

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 baseline is 3; the description itself adds nothing about the two parameters (days and status) beyond what the schema already documents. The schema descriptions are rich, particularly the status parameter's explanation of omitted-state behavior, so no additional compensation is needed.

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 ('Read') and resource ('every Google Ads keyword'), and enumerates the returned data (effective CPC bid, approval and serving status, metrics). The 'Returns every row rather than a first page' clause distinguishes this from sibling tools like ads_query or ads_campaigns by highlighting the full-fetch behavior.

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 description implies when to use the tool: when you need the complete keyword set and an accurate count, noting that console counts omit rows. However, it does not explicitly name alternative tools or state conditions for choosing this tool over siblings like ads_query or ads_search_terms, leaving the routing largely implicit.

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

ads_negativesA

Read the negative keywords already in place, at campaign, ad group or shared-set level. A negative blocks traffic without leaving any record that it did, so this is what to check when a keyword stops serving and nothing looks wrong, and what to check before adding a term twice; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
levelNoWhich negatives to read. A term blocked at campaign level is blocked everywhere in it; a shared set applies to every campaign it is attached toall

Output Schema

ParametersJSON Schema
NameRequiredDescription
notesYes
rowCountYes
negativesYes

TDQS

A4.9/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden of disclosing safety and behavior. It explicitly says 'read-only' and explains that a negative blocks traffic without leaving a record—important context that influences how the agent interprets search results. This goes beyond the schema and adds meaningful behavioral insight.

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 sentences with zero fluff. The core purpose is stated first, followed by practical usage guidance. Every clause earns its place—no redundant phrasing or boilerplate.

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?

Given that an output schema exists, the return format is already covered. The description fully explains what the tool does, when to use it, and the nuances of the parameter. It is complete for an agent to decide when and how to invoke it, with nothing critical 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?

The schema already documents the 'level' parameter with a 100% description coverage, including its enum values. The description adds extra semantic context about the scoping behavior (campaign-level blocks apply everywhere in the campaign; shared sets apply to all attached campaigns), which enriches understanding beyond the raw schema. Since schema coverage is complete, a 4 is 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 clearly states the action: read negative keywords at campaign, ad group, or shared-set level. It distinguishes itself from siblings like ads_negatives_update (which implies write) by explicitly noting this is a read-only check, and it is unambiguous about what resource it operates on.

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 gives explicit when-to-use scenarios: check when a keyword stops serving with no apparent cause, and check before adding a term twice to avoid duplication. These are concrete triggers that guide the agent toward this tool over alternatives. It also states the read-only nature, which helps the agent avoid using a mutating tool by mistake.

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

ads_negatives_updateA

Add or remove negative keywords in a batch, enumerated one by one with no pattern form. Before adding, every proposed negative is checked against the campaign's own live keywords and the batch is refused if one would block traffic, because a wrong negative leaves no evidence anywhere: the traffic just stops. Dry run unless dryRun is false, and the terms are read back afterwards

ParametersJSON Schema
NameRequiredDescriptionDefault
levelNoWhere the negatives live. A campaign-level negative blocks the term everywhere in that campaigncampaign
actionYesAdd negative keywords or remove existing ones. Removal matters as much as adding: a wrong negative shows up as nothing at all
dryRunNoReport what would change, and which proposed negatives would block a live keyword, without changing anything
targetYesThe campaign or ad group name. It must match exactly one or nothing is changed
confirmNoPerform the batch even though a guard tripped. The dry run lists what tripped, so this confirms something already read
keywordsYesThe negative terms, enumerated one by one. There is no pattern or match-all form: a selector is one typo away from blocking a whole campaign
matchTypeNoHow each term blocks. BROAD blocks any query containing all its words, which is the setting that can silently kill a campaignEXACT

Output Schema

ParametersJSON Schema
NameRequiredDescription
levelYes
notesYes
actionYes
guardsYes
targetYes
appliedYes
changedYes
skippedYesTerms not sent, because they are already present when adding or absent when removing
matchTypeYes
requestedYes
collisionsYesProposed negatives that would stop one of this campaign's own live keywords from serving. This is the error that otherwise produces no evidence at all

TDQS

A4.4/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden of disclosure and does so excellently. It reveals the dry-run default, the guard that refuses the batch if a negative would block traffic, the rationale (silent traffic loss), and that terms are read back. It also clarifies the consequence of a wrong negative, which is critical behavioral context beyond 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 sentences with no wasted words. It front-loads the core purpose, then immediately provides the most important behavioral guard, and finishes with dry-run and read-back behavior. Every clause earns its place and the density is appropriate for the complexity.

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 complex 7-parameter tool with no annotations and an output schema, the description covers most key behavioral nuances: guard, dry-run, read-back, and the enumerated-list constraint. The notable gap is that it says the batch is 'refused if one would block traffic' without mentioning that confirm can override the guard, which is a significant behavioral path. The schema covers confirm, but the description's narrative is slightly incomplete on that interaction.

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, and the description adds meaningful operational meaning to several parameters: keywords are explicitly enumerated with no pattern form, dryRun's default behavior is stated, and the guard logic clarifies action and confirm's context. It does not systematically walk through each parameter but enhances the schema descriptions with non-obvious implications.

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-resource pair ('Add or remove negative keywords in a batch') and adds a distinguishing constraint ('enumerated one by one with no pattern form'). It clearly differentiates from siblings like ads_negatives (which likely reads negatives) and ads_keyword_create (single keyword creation), so an agent can tell it apart 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 Guidelines3/5

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

The description implies usage context (batch operations, no patterns) but never explicitly says when to use this tool over alternatives like ads_update_batch or ads_keyword_create. It does not name any sibling or exclusion condition, leaving the agent to infer the appropriate choice from the name and purpose alone.

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

ads_queryA

Run an arbitrary GAQL SELECT against the Google Ads account for a question the shaped reads do not cover. GAQL has no statement other than SELECT, so this cannot change anything; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesA GAQL SELECT statement. GAQL has no other statement, so this cannot change anything

Output Schema

ParametersJSON Schema
NameRequiredDescription
rowsYes
queryYes
rowCountYes

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations provided, the description carries full behavioral disclosure. It explicitly states that GAQL has no statement other than SELECT and therefore the operation cannot change anything, establishing it as read-only. It does not mention rate limits, query timeouts, or result-size limits, but the core safety behavior is transparently disclosed.

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 deliver the purpose, the usage context, and the read-only guarantee with no filler. The information is front-loaded and every clause earns its place.

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?

Given a single parameter, an output schema, and the explicit read-only guarantee, the description covers what an agent needs to invoke the tool correctly. It could name a few shaped-read siblings to make the fallback role more concrete, but the generic reference is sufficient for routing.

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 coverage is 100%, so the schema already documents the single query parameter as a GAQL SELECT statement. The description reinforces the GAQL semantics and the read-only property, but adds little beyond what the schema provides, so the baseline of 3 is 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?

Description states a specific verb ('Run'), a specific resource ('Google Ads account'), and the exact mechanism ('arbitrary GAQL SELECT'). It also positions the tool as the fallback for questions the shaped reads do not cover, clearly distinguishing it from the many ads_* sibling reads.

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?

The phrase 'for a question the shaped reads do not cover' gives clear guidance on when to use this tool as the general-purpose fallback versus the more targeted shaped reads. It does not name specific siblings or give explicit negative examples, but the context is clear enough for an agent to route correctly.

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

ads_search_termsA

Read the queries that actually triggered an ad, with the keyword each one matched and its metrics. This is the paid equivalent of the Search Console query dimension. Google withholds terms too few people searched, so an absent term is unknown rather than absent; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoHow many days back to report, ending today
minCostNoDrop search terms that cost less than this over the window
minImpressionsNoDrop search terms below this many impressions
zeroConversionsOnlyNoKeep only terms that converted nothing, which is the list that feeds negative keywords

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
notesYes
rowCountYes
searchTermsYes

TDQS

A4/5.0
Behavior4/5

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

No annotations are present, so the description carries the full burden. It explicitly states 'read-only' and discloses an important data behavior: 'Google withholds terms too few people searched, so an absent term is unknown rather than absent'. This adds meaningful context beyond the tool name. It does not mention authentication, rate limits, or pagination, but the output schema covers return format, so this is sufficient.

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 sentences with no filler. The core purpose and the key behavioral caveat are front-loaded, and the read-only note is appended efficiently. Every sentence earns its place.

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 read-only tool with a clear output schema and four optional parameters, the description covers the essential context: what data it returns, the comparison to organic queries, and the data withholding nuance. It doesn't explain prerequisites like authentication or campaign selection, but these are likely common across the toolset and not critical for this simple read operation.

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 coverage is 100% and each parameter has a descriptive explanation (e.g., 'Drop search terms below this many impressions'). The main description does not add additional meaning about parameters beyond what the schema already provides, so it meets the baseline but does not exceed it.

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 uses a specific verb ('Read') and identifies the exact resource ('queries that actually triggered an ad') and the data returned (keyword and metrics). It also distinguishes itself from the organic equivalent by calling itself the 'paid equivalent of the Search Console query dimension', which helps an agent separate it from sibling tools like search_analytics. This is a clear, specific purpose statement.

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 description provides a useful comparison to Search Console but does not explicitly name alternative tools or state when not to use this one. It implies this is for paid search queries, but an agent would need to infer that organic queries belong elsewhere. There is no explicit routing to sibling tools like ads_keywords or search_analytics, leaving some ambiguity.

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

ads_updateA

Change one Google Ads keyword bid, campaign daily budget, campaign status, ad status or keyword status. Pausing one keyword is its own kind because dropping a bid is not the same thing: the keyword stays eligible and goes on competing for the same budget. Spends money, so it is a dry run unless dryRun is false, it refuses a change that trips a guard unless confirm is true, and it re-reads the value after writing because an accepted request is not a stored value. Guards: more than three times the current amount, more than $25, or pausing something that is serving

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYesWhat to change: a keyword's max CPC bid, a campaign's daily budget, a campaign's status, an ad's status, or a keyword's status. Use keywordStatus to stop one keyword serving; dropping its bid is not the same thing, because the keyword stays eligible and keeps competing for the same budget
valueYesThe new amount in dollars for a bid or budget, or pause or enable for a status
dryRunNoReport what would change and which guards it trips, without changing anything. On by default: this tool spends money, so performing a change has to be asked for
targetYesThe keyword text, the campaign name, or the numeric ad id. It must match exactly one thing or the call is refused
confirmNoPerform a change that trips a guard. Ignored on a dry run. The dry run lists the guard reasons, so this confirms something already read rather than something unseen

Output Schema

ParametersJSON Schema
NameRequiredDescription
kindYes
noOpYes
afterYes
beforeYes
guardsYes
targetYes
appliedYes
matchesYesWhether the re-read value equals what was sent
readBackYesThe value re-read from the account after the write. An accepted request is not proof of a stored value
customerIdYes

TDQS

A4.4/5.0
Behavior5/5

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

With no annotations provided, the description carries full burden of behavioral disclosure. It explicitly states the tool spends money, defaults to a dry run, requires confirm to override guards, and re-reads values after writing because an accepted request may not be a stored value. It also enumerates the guard conditions, making the behavior fully transparent.

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 dense and covers multiple aspects, but it is not excessively long. It front-loads the purpose and then explains nuanced behaviors. While it could be structured more clearly with separate sentences for each behavioral note, it remains concise enough and each clause adds value.

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?

The description is comprehensive for a tool with this complexity. It covers the dry run behavior, guard conditions, confirmation requirement, and the distinction between bid and status changes. Since an output schema exists, the description need not explain return values, and nothing critical is missing for an agent to call this tool 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?

Schema description coverage is 100%, so parameters are well-documented. The description adds meaningful context beyond the schema, explaining the relationship between bid and status, and the semantics of dryRun and confirm. It clarifies that dryRun is on by default and why, which is not evident from the schema alone.

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 clearly states the tool's function: changing one specific ads entity (bid, budget, status). It also distinguishes between changing a bid and pausing a keyword, which differentiates it from sibling tools that might do similar actions. The resource is specified exactly.

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 description implies when to use this tool (for single changes) and clarifies that pausing a keyword is distinct from lowering its bid. However, it does not explicitly name alternative tools like ads_update_batch or ads_negatives_update, leaving the when-not-to-use guidance implicit rather than explicit.

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

ads_update_batchA

Change several Google Ads keyword bids, or several campaign daily budgets, in one call. It is a named list of pairs, not a rule applied to many things: each entry names one target and the value it should end at, and an entry that matches no row or more than one refuses the whole batch before anything is written. The sum is guarded as well as each entry, because separately reasonable raises are one large spend change together. Dry run unless dryRun is false, and every value is read back afterwards

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYesOne kind per call. A summed guard is only honest inside one kind: bids and budgets sum to dollars, statuses do not, and mixing them makes the total unreadable
dryRunNoResolve and price every entry and report the total, without changing anything
changesYesA named list of pairs, each with its own value. There is no selector form: enumeration cannot make the mistake that a pattern can
confirmNoPerform the batch even though a guard tripped. The dry run lists every reason, so this confirms something already read

Output Schema

ParametersJSON Schema
NameRequiredDescription
kindYes
notesYes
appliedYes
entriesYes
customerIdYes
totalAfterYes
totalBeforeYesNull when any entry has no current value to read, because a total that counts unknowns as zero is not a total
totalGuardsYesGuards on the batch as a whole. Five individually reasonable raises are one large spend change, and doing them one at a time is how that gets missed
totalSummaryYesThe batch total in words, always present whether or not anything tripped. The sentence is what gets read; the guard is only what stops you when it is not

TDQS

A4.5/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden, and it delivers: it discloses dry-run behavior, atomic refusal when an entry matches zero or many rows, per-entry and summed spend guards, and read-back verification after writing. These are critical behavioral details that go well beyond what the schema alone reveals.

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 compact, front-loaded with the main purpose, and each sentence adds a distinct behavioral guarantee. Nothing is redundant or filler; the length is appropriate for the tool's complexity.

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 guarded batch mutation tool with a complex failure model, the description covers the essential invocation constraints, safety behavior, and post-write verification. The output schema handles return-value documentation, so the description is sufficiently complete for an agent to call the tool correctly.

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?

The input schema already has rich descriptions for all four parameters, so the baseline is 3. The description reinforces key meanings, such as the kind restriction and the named-pair form of changes, but it does not add substantial semantic detail beyond the schema's own parameter documentation.

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 starts with a specific verb and resource: changing several Google Ads keyword bids or campaign daily budgets in one call. It clearly distinguishes this batch tool from a rule-based or singular update, making the tool's scope immediately recognizable relative to siblings like ads_update.

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 clearly implies when to use the tool: when updating multiple named targets in one call. It describes the intended shape as an explicit list of pairs rather than a broad rule, which guides appropriate invocation. It does not explicitly name alternative sibling tools, but the context is sufficient for an agent to decide when this batch operation is appropriate.

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

app_store_discoveryA

Read the App Store surfaces beyond the listing text: search keywords, app tags, product page optimization experiments, custom product pages, in-app events, territory availability and review summarizations. A resource this key cannot read is reported as unavailable rather than as empty. Read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
appIdNoApp Store Connect numeric app id; provide this or bundleId
limitNoRows per resource
includeNoWhich discovery surfaces to read; empty reads all of them
localesNoLocales for per-locale resources such as searchKeywords
bundleIdNoBundle id; provide this or appId
platformNoPlatform for resources that require oneIOS
includeRowsNoInclude every raw row as well as the counts; off by default so a summary call stays small

Output Schema

ParametersJSON Schema
NameRequiredDescription
appIdYes
notesYes
localesYes
bundleIdYes
resourcesYes

TDQS

A4.4/5.0
Behavior5/5

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

Since annotations are absent, the description carries full behavioral burden. It explicitly states read-only and explains that unavailable resources are reported as unavailable rather than empty, which is a key behavioral nuance beyond typical read operations. This is valuable transparency.

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 concise, front-loaded with the core purpose, and every sentence contributes. It efficiently lists surfaces and key behaviors without fluff. The read-only note is placed at the end, which is appropriate as a secondary detail.

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?

Given the high schema coverage and presence of an output schema, the description is quite complete. It covers the behavior on missing resources and confirms read-only. Potential gaps like pagination or error handling are insufficient to call it incomplete for a read-only tool with comprehensive schema.

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?

The schema covers 100% of parameters, so baseline 3 applies. The description doesn't add much beyond what the schema already describes, but it does mention 'territory availability' which aligns with the availability enum. No additional depth is provided, but it's sufficient given the schema's completeness.

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 clearly lists the specific surfaces (search keywords, tags, experiments, etc.), indicating the verb 'read' and the resource 'App Store discovery surfaces'. It clearly differentiates from siblings like app_store_listing or app_store_reviews by focusing on non-listing data.

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 implies when to use via the surface enumeration, but does not explicitly state when not to use compared to app_store_listing or app_store_reviews. However, the targeted 'beyond the listing text' gives context. Sibling alternatives like app_store_reviews are evident, but no explicit exclusion is made.

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

app_store_listingA

Read an App Store listing's indexed fields per locale (name, subtitle, keywords) against Apple's character limits, plus promotional text, version state and star ratings. The ratings come from the public storefront lookup because App Store Connect exposes no aggregate rating; each entry names its source. Needs SEO_MCP_ASC_KEY_PATH, SEO_MCP_ASC_KEY_ID and SEO_MCP_ASC_ISSUER_ID; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
appIdNoApp Store Connect numeric app id; provide this or bundleId
stateNoRead the live listing or the editable one being prepared for releaselive
bundleIdNoBundle id, resolved to an app id when appId is not given; provide this or appId
platformNoApp Store platform whose version is readIOS
storefrontsNoStorefront country codes for the public ratings lookup

Output Schema

ParametersJSON Schema
NameRequiredDescription
appIdYes
notesYes
localesYes
ratingsYes
bundleIdYes
fellBackYes
platformYes
ageRatingYes
overLimitYes
categoriesYes
localeCountYes
appInfoStateYes
versionStateYes
hasLiveRecordYes
phasedReleaseYes
versionStringYes
requestedStateYes
hasEditableRecordYes

TDQS

A4.1/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and explicitly labels the operation read-only. It also discloses the unusual ratings source (public storefront lookup because App Store Connect exposes no aggregate rating) and that each entry names its source, which is genuinely useful behavioral context beyond 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?

Three sentences with no filler, opening with the core operation and then covering ratings provenance and auth requirements. Every sentence carries operational information and the most important detail is front-loaded.

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 read-only tool with a full output schema and 100% parameter coverage, the description supplies purpose, behavior, authentication, and data provenance. Nothing needed to invoke it correctly is missing, and the output schema covers return-value 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?

All five parameters have detailed schema descriptions, so the baseline is 3. The description adds contextual meaning by tying name/subtitle/keywords to Apple's character limits and explaining why storefronts are used for ratings, but it does not map or extend individual parameter semantics beyond the schema.

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 (Read) and a concrete resource (App Store listing's indexed fields per locale, promotional text, version state, star ratings), which clearly distinguishes it from siblings like app_store_reviews or app_store_discovery. It also adds the meaningful constraint of checking against Apple's character limits.

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 description implies its use through the list of read operations but never states when to choose it over alternatives or when not to use it. The auth-key requirement is operational context, not usage guidance. An agent would have to infer the appropriate context from the tool name and description alone.

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

app_store_reviewsA

Read App Store customer reviews and your responses, filtered by rating or storefront. Reports the mean and star split of the reviews actually fetched, which is not the app's lifetime rating; App Store Connect exposes no aggregate rating resource. Read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
sortNoSort order; newest first by default-createdDate
appIdNoApp Store Connect numeric app id; provide this or bundleId
limitNoMaximum reviews to return across pages
ratingNoOnly these star ratings
bundleIdNoBundle id; provide this or appId
maxPagesNoMaximum pages to follow
territoryNoOnly reviews from this storefront

Output Schema

ParametersJSON Schema
NameRequiredDescription
appIdYes
notesYes
filtersYes
reviewsYes
bundleIdYes
returnedYes
pagesReadYes
meanOfFetchedYes
withoutResponseYes
histogramOfFetchedYes

TDQS

A4.2/5.0
Behavior4/5

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

The description discloses a key behavioral trait: the reported mean and star split are computed from the fetched reviews, not the app's lifetime rating, and that App Store Connect exposes no aggregate rating resource. This is valuable context beyond the schema. However, it does not mention pagination behavior, rate limits, or whether responses are included by default, which are minor gaps given the schema already documents pagination parameters.

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 sentences with no wasted words. It front-loads the core action and resource, then adds the critical caveat about the aggregate rating. Every sentence earns its place.

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?

The description is complete for a read-only review-fetching tool. It explains the key caveat about the aggregate rating, and the schema covers all parameters. It could mention whether responses are included by default or how pagination works, but the schema's maxPages and limit parameters already imply pagination. The output schema exists, so return values need not be described.

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 all 7 parameters. The description adds context about the meaning of the returned aggregate (mean and star split) but does not add new parameter-level semantics beyond what the schema provides. Baseline 3 is 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 ('Read'), a specific resource ('App Store customer reviews and your responses'), and explicit filtering dimensions ('by rating or storefront'). It also distinguishes itself from a potential confusion by clarifying that the reported mean/split is not the app's lifetime rating, which is a meaningful differentiator from other app-related tools.

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?

The description clearly implies when to use this tool: when you need App Store reviews or responses, optionally filtered by rating or storefront. It does not explicitly name alternative tools or state when not to use it, but the context of sibling tools (e.g., app_store_sales, play_store_stats) makes the use case reasonably clear. The clarification about the aggregate rating resource also helps set expectations.

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

app_store_salesA

Read App Store Sales and Trends: units downloaded per day per territory per app, summarized by SKU. Needs SEO_MCP_ASC_VENDOR_NUMBER and a team key with Admin, Finance or Sales and Reports. A period with no sales is reported as an absence rather than an error. Read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
versionNoReport version, such as 1_0 or 1_3, when the default is not accepted
frequencyNoReport periodDAILY
reportDateNoReport date. DAILY and WEEKLY take YYYY-MM-DD (WEEKLY means the week's ending date), MONTHLY takes YYYY-MM, YEARLY takes YYYY. Defaults to the most recent complete period for the frequency
reportTypeNoSales and Trends report typeSALES
includeRowsNoInclude every raw report row as well as the per-SKU summary
reportSubTypeNoReport sub typeSUMMARY

Output Schema

ParametersJSON Schema
NameRequiredDescription
appsYes
rowsYes
notesYes
hasDataYes
rowCountYes
frequencyYes
reportDateYes
reportTypeYes
totalUnitsYes
vendorNumberYes
reportSubTypeYes

TDQS

A4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does well: it explicitly states the operation is read-only, lists required credentials and role permissions, and discloses the no-sales absence behavior. It could go further with rate limits or response shape expectations, but the output schema covers the latter.

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?

Three sentences deliver purpose, prerequisites, and an edge case with zero filler. The most important information is front-loaded in the first sentence, and every sentence earns its place.

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 six-parameter tool with a full output schema, the description covers purpose, authentication, role requirements, read-only behavior, and a notable edge case. It is nearly complete, though it stops short of guiding the agent on when to choose this sibling over other app store tools.

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 all six parameters with defaults and formats. The description adds contextual meaning about the report contents, but does not provide parameter-level guidance beyond what the schema already offers.

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 opens with 'Read App Store Sales and Trends' and specifies the exact data granularity ('units downloaded per day per territory per app, summarized by SKU'). This clearly distinguishes it from Play Store and other app store sibling tools, even without naming them.

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 description implies usage context by stating it reads App Store Sales and Trends, and it provides credential prerequisites. However, it does not explicitly say when to prefer this tool over alternatives such as play_store_stats or app_store_listing, nor does it list any exclusion conditions.

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

audit_siteA

Audit the on-page SEO of up to N pages from a sitemap and roll up the most common issues across the site. Takes a sitemap URL rather than a Search Console property, and needs no Google credentials

ParametersJSON Schema
NameRequiredDescriptionDefault
maxPagesNoMaximum pages to audit
sitemapUrlYesPublic sitemap URL to audit
concurrencyNoMaximum page fetches in flight

Output Schema

ParametersJSON Schema
NameRequiredDescription
pagesYes
failedYes
rollupYes
auditedYes
skippedYes
truncatedYes
sitemapUrlYes
totalDiscoveredYes
childSitemapsFailedYes
childSitemapsSkippedYes

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral burden. It discloses that the tool audits up to N pages, aggregates issues, requires only a sitemap URL, and does not need Google credentials. It does not mention potential side effects or rate limiting, but 'audit' implies a read-only operation and the key behavioral constraints are clearly stated.

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 compact sentences deliver the core purpose, the input requirement, and the authentication context without any filler. Key constraints are front-loaded, and the sentence structure makes the tool's scope immediately clear.

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?

Given the 3-parameter schema, high schema coverage, and the presence of an output schema, the description is sufficiently complete for an agent to select and invoke the tool. It explains the input type, scope, aggregation behavior, and auth requirement; the remaining details, such as concurrency defaults, are already present in the structured schema.

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 baseline is 3. The description adds marginal value by linking 'up to N pages' to maxPages and confirming sitemapUrl is the input, but it does not explain concurrency or add meaningful detail beyond what the schema already provides.

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 uses a specific verb ('Audit') and names the exact resource ('on-page SEO of up to N pages from a sitemap'), then clarifies the output ('roll up the most common issues'). It also distinguishes itself from Search Console-based tools by explicitly stating it takes a sitemap URL and needs no Google credentials.

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?

The description gives clear usage context: use it when you have a public sitemap and want a site-wide rollup of common on-page SEO issues. It implies an alternative path ('rather than a Search Console property') but does not explicitly name a sibling tool or state when not to use it.

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

compare_search_periodsB

Compare an analysis window with the preceding equal period to identify search gainers and losers

ParametersJSON Schema
NameRequiredDescriptionDefault
byNoDimension used to compare performancequery
limitNoMaximum gainers and losers to return; defaults to 50 each
endDateNoEnd date in YYYY-MM-DD; defaults to today
siteUrlYesSearch Console property to analyze
startDateNoStart date in YYYY-MM-DD; defaults to the latest 28-day window

Output Schema

ParametersJSON Schema
NameRequiredDescription
losersYesRows with decreased clicks
gainersYesRows with increased clicks
siteUrlYesSearch Console property analyzed
currentWindowYesCurrent comparison window
previousWindowYesImmediately preceding equal-length window
currentTruncatedYesWhether Search Console held more than 5000 rows for the current window
droppedAsUnknownYesRows present on only one side whose other side was cut off, and so were excluded rather than counted as zero
previousTruncatedYesWhether Search Console held more than 5000 rows for the previous window

TDQS

B3.3/5.0
Behavior3/5

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

With no annotations, the description carries the full burden of behavioral disclosure. It does convey the key non-obvious behavior of comparing against the preceding equal-length period, and 'compare' implies a non-mutating read operation. However, it does not explicitly state that the tool is read-only, nor mention any rate limits, required permissions, or other side effects.

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. Every word contributes to understanding the tool's core behavior and output. Length is appropriate for the tool's complexity.

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?

Description is adequate given that an output schema exists and all parameters are documented. However, it does not clarify how gainers/losers are computed or what metric drives the comparison, and it relies on the user to infer the default 28-day window behavior from the schema. Sufficient for invocation, but not rich.

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 baseline is 3. The description adds no parameter-specific meaning beyond what the schema already documents; it only frames the overall use case (comparing windows to find gainers/losers), which is already implied by the parameter descriptions.

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 uses a specific verb ('Compare') with a clear resource ('an analysis window with the preceding equal period') and states the intended output ('identify search gainers and losers'). This distinguishes it from raw analytics tools like search_analytics, though it does not explicitly name any sibling or contrast itself with them.

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?

The description implies when the tool is useful (when you need period-over-period gainers/losers) but provides no explicit guidance on when to use it over alternatives such as search_analytics, ctr_gaps, or compare_snapshots. No exclusions, prerequisites, or routing cues are given.

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

compare_snapshotsA

Compare two snapshot documents and return the differences between them: clicks, impressions, positions, installs, ratings and locale counts. Reports arithmetic only, never whether a change was good or what caused it; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesSnapshot file name or path inside the snapshot directory; latest names the newest snapshot on disk and previous the one before it
fromYesSnapshot file name or path inside the snapshot directory; latest names the newest snapshot on disk and previous the one before it
minImpressionsNoIgnore page position moves below this many impressions on both sides

Output Schema

ParametersJSON Schema
NameRequiredDescription
toYes
appsYes
fromYes
notesYes
slugsYes
packagesYes
propertiesYes
elapsedHoursYes
minImpressionsYes
argumentsReversedYes
surfacesWithErrorsYes

TDQS

A4.2/5.0
Behavior4/5

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

The description explicitly states 'Reports arithmetic only, never whether a change was good or what caused it; read-only'. This goes beyond the schema and annotations (which are absent) by disclosing the tool's interpretive limits and safety profile. It tells the agent the tool will not provide causal or evaluative analysis, which is valuable behavioral context. It could add more about output format or error cases, but the core behavioral traits are well covered.

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 sentences with no wasted words. The core action and compared fields are front-loaded, and the behavioral caveat ('arithmetic only... read-only') is placed at the end where it supplements rather than obscures the main purpose. Every sentence earns its place.

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?

The tool has an output schema, so return values are already structured. The description covers the tool's purpose, scope, and behavioral limits. It doesn't mention edge cases like what happens if a snapshot doesn't exist or if from/to are the same, but the schema's parameter descriptions and the output schema reduce the need for that. For a read-only comparison tool, this is nearly complete.

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 all three parameters thoroughly, including the special values 'latest' and 'previous' for from/to and the default/min/max for minImpressions. The description adds the list of compared fields, which gives context for what the parameters affect, but it doesn't add new parameter-level semantics beyond the schema. Baseline 3 is 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 ('Compare'), a specific resource ('two snapshot documents'), and the exact fields compared ('clicks, impressions, positions, installs, ratings and locale counts'). It also distinguishes itself from siblings by focusing on snapshot comparison, which is unique among the listed tools. The scope is clear and an agent can select it 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 Guidelines4/5

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

The description implies when to use this tool: when comparing two snapshots and needing arithmetic differences. It does not explicitly name alternatives or exclusions, but the sibling list contains related tools like compare_search_periods and list_snapshots, and the description's focus on snapshots makes the usage context clear. It lacks an explicit 'use X instead when...' statement, so it doesn't earn a 5.

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

crux_field_dataA

Read real-user Core Web Vitals for an origin or URL from the Chrome UX Report: the current 28-day field record with p75s and histograms. Field data, not a lab test; PageSpeed's own field block is being discontinued. Needs SEO_MCP_CRUX_KEY or a PageSpeed key allowed to call the Chrome UX Report API; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoA single page URL. Give origin or url, not both
originNoOrigin such as https://example.com; aggregates every page under it. Give origin or url, not both
metricsNoMetric names to request; omit for all available
formFactorNoDevice class; omit for all form factors combined

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlYes
notesYes
originYes
sourceYes
hasDataYes
metricsYes
formFactorYes
normalizedUrlNo
collectionPeriodNo

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It states the tool is read-only, requires a specific API key, and returns the current 28-day field record with p75s and histograms. It also notes the PageSpeed field block is being discontinued, which is useful context. It doesn't detail error behavior or rate limits, but the read-only and data-scope disclosure is solid.

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 a single compact paragraph that front-loads the core purpose, then adds the field-vs-lab distinction, the key requirement, and the read-only note. Every sentence earns its place with no redundancy.

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?

The description is complete for a read-only data-fetching tool: it covers the data source, scope, key requirement, and read-only nature. The output schema exists, so return values are documented elsewhere. Minor gaps like pagination or error handling are not critical for this tool's complexity.

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 all four parameters. The description adds the key context that origin aggregates every page under it and that metrics can be omitted for all available, but these are largely restatements of the schema descriptions. Baseline 3 is 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 clearly states the tool reads real-user Core Web Vitals from the Chrome UX Report for an origin or URL, with p75s and histograms. It explicitly distinguishes field data from lab tests and names the sibling crux_history as the historical counterpart, making it easy for an agent to select the right tool.

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?

The description explicitly says when to use this tool (for current 28-day field data) and contrasts it with lab tests and the discontinued PageSpeed field block. It also names the sibling crux_history, implying the historical alternative, and states the API key requirement. This is strong routing guidance.

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

crux_historyA

Read the Chrome UX Report weekly history for an origin or URL, roughly six months of 28-day rolling windows, so a field metric can be seen trending rather than as one point. Read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoA single page URL. Give origin or url, not both
originNoOrigin such as https://example.com; aggregates every page under it. Give origin or url, not both
metricsNoMetric names to request; omit for all available
formFactorNoDevice class; omit for all form factors combined
collectionPeriodCountNoWeekly periods to return, 1 to 40. Documented history is about six months; the API decides what it actually has

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlYes
notesYes
originYes
sourceYes
hasDataYes
metricsYes
formFactorYes
periodCountNo
normalizedUrlNo
collectionPeriodsNo

TDQS

A4.2/5.0
Behavior4/5

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

No annotations are present, so the description carries the behavioral disclosure burden. It explicitly labels the operation 'Read-only' and sets expectations about the data window and rolling-period structure. It does not describe ordering or availability caveats, but the output schema is present and the read-only nature is made clear.

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 tight sentences with no filler. The core action and resource are front-loaded, and the secondary detail about the rolling-window format earns its place. 'Read-only' is a concise behavioral flag.

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 read-only history tool with fully described parameters and an output schema, the description covers the important context: resource, time range, and purpose. It could name the direct alternative (crux_field_data) more explicitly, but the one-point-vs-trend distinction already provides adequate orientation.

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?

All 5 parameters have schema descriptions, so coverage is 100%. The description reinforces the origin/URL distinction and the trending purpose, but it does not add significant meaning beyond what the schema already provides for metrics, formFactor, or collectionPeriodCount.

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: 'Read the Chrome UX Report weekly history for an origin or URL.' It also defines the scope: roughly six months of 28-day rolling windows. It distinguishes the tool from a one-point read by saying it shows a metric 'trending rather than as one point,' which separates it from crux_field_data.

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?

The description clearly implies the right context: when you need to see a field metric's trend over time rather than a single snapshot. It does not explicitly name an alternative or state exclusions, but the 'rather than as one point' contrast gives an agent a usable selection heuristic.

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

ctr_gapsA

Find high-impression queries or pages whose CTR trails peers at the same position for snippet rewrite prioritization

ParametersJSON Schema
NameRequiredDescriptionDefault
byNoDimension used to identify CTR gapsquery
limitNoMaximum gaps to return; defaults to 50
endDateNoEnd date in YYYY-MM-DD; defaults to today
siteUrlYesSearch Console property to analyze
startDateNoStart date in YYYY-MM-DD; defaults to the latest 28-day window
minImpressionsNoMinimum impressions required; defaults to 100

Output Schema

ParametersJSON Schema
NameRequiredDescription
gapsYesRows underperforming their position peers
windowYesAnalysis window
siteUrlYesSearch Console property analyzed
truncatedYesWhether Search Console held more than 5000 rows for this window, so the list was computed from the top rows only

TDQS

A3.8/5.0
Behavior3/5

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

Annotations are absent, so the description must carry behavioral disclosure. It indicates a read-only analytical nature ('Find high-impression queries...') but does not state whether it is read-only or if it requires specific permissions. The output schema exists, so return format is covered, but there is no warning about rate limits or potential data freshness issues.

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 a single, well-structured sentence that front-loads the core purpose (Find high-impression queries or pages) and immediately states the specific use case. There is no wasted wording; it is efficient and to the point.

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?

Given the tool's analytical complexity, an output schema that covers the result, and full schema parameter coverage, the description provides sufficient context. It could mention default behaviors (like date range or minImpressions) but those are in the schema. The only minor gap is lack of explicit relation to peers or how the gap is computed, but that may be covered by the output schema.

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 parameter semantics are already fully documented in the schema. The description adds minimal extra meaning beyond the schema, only reinforcing the dimension of query vs page. Baseline 3 is appropriate as the schema fully documents each parameter.

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 clearly states the tool's purpose: identifying high-impression queries or pages with CTR gaps relative to peers at the same position, explicitly for snippet rewrite prioritization. It distinguishes this from generic analytics tools like search_analytics by focusing on CTR gaps and the specific use case.

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 description implies use for snippet rewrite prioritization but does not explicitly mention when not to use it or alternative tools. Siblings like search_analytics could also provide CTR data, but no guidance is given on when to choose this tool over them. The context is clear enough for a knowledgeable agent.

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

delete_sitemapA

Remove a submitted sitemap from a Search Console property (write; supports dryRun)

ParametersJSON Schema
NameRequiredDescriptionDefault
dryRunNoIf true, report what would be removed without writing to Search Console
siteUrlYesSearch Console property
feedpathYesAbsolute URL of the sitemap to remove

Output Schema

ParametersJSON Schema
NameRequiredDescription
dryRunNo
siteUrlYes
successYes
feedpathYes

TDQS

A3.6/5.0
Behavior3/5

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

No annotations are provided, so the description carries the burden of behavioral disclosure. It does add 'write' and 'supports dryRun,' which signal mutation and a preview capability beyond the tool name. However, it omits whether deletion is irreversible or whether special permissions are required, leaving only partial transparency.

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 a single efficient sentence that front-loads the core purpose and immediately surfaces the dryRun capability. There is no filler or redundant repetition of the schema.

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 simple 3-parameter delete operation with full schema coverage and an output schema present, the description covers the essential purpose and dryRun behavior. It lacks an explicit irreversibility caveat, but the 'write' label partially compensates for the missing annotations, making the description adequate for correct invocation.

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 siteUrl, feedpath, and dryRun with meaningful details. The description only repeats dryRun's existence without adding new semantic value, so the baseline of 3 is 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 ('Remove'), a clear resource ('submitted sitemap'), and a target ('Search Console property'), which distinguishes it from related siblings like submit_sitemap and list_sitemaps. The parenthetical 'write' also clarifies the mutation type immediately.

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 tool versus list_sitemaps or submit_sitemap. It does not mention that a user should first list sitemaps to obtain the feedpath, nor does it warn about destructive effects beyond the terse 'write' label. The dryRun option is mentioned but not framed as a recommended workflow.

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

index_coverageA

Check how many of a sitemap's pages are indexed by Google (bounded; respects URL Inspection quota)

ParametersJSON Schema
NameRequiredDescriptionDefault
maxUrlsNoMaximum URLs to inspect
siteUrlYesSearch Console property containing the sitemap URLs
sitemapUrlYesFully qualified sitemap URL to inspect
concurrencyNoConcurrent URL Inspection requests

Output Schema

ParametersJSON Schema
NameRequiredDescription
failedYes
checkedYes
indexedYes
resultsYes
siteUrlYes
truncatedYes
notIndexedYes
sitemapUrlYes
totalDiscoveredYes
childSitemapsSkippedYes

TDQS

A3.8/5.0
Behavior4/5

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

The description notes it is bounded and respects URL Inspection quota, which is useful behavioral context beyond the schema. It does not mention potential rate limiting or that it makes multiple requests, but the quota note is valuable. No annotations provided, so description carries burden.

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 a single concise sentence (24 words) that packs in purpose and the key quota note. It's front-loaded and efficient, with no wasted words.

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?

Given the tool's moderate complexity and an output schema present, the description is sufficient. It covers the core function and a key constraint. It might benefit from mentioning it returns a summary of indexed vs total, but the output schema likely covers that. Overall, adequate.

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?

The schema covers all parameters with descriptions, so parameter semantics are well covered by schema. The description adds little beyond the schema, but with 100% coverage, a baseline of 3 is appropriate. It does not add new meaning.

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 clearly states the tool checks how many sitemap pages are indexed by Google, with a specific verb and resource. It distinguishes from list_sitemaps and submit_sitemap, but the sibling 'inspect_url' could overlap. It is specific enough.

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 description implies usage: when you need to know index coverage of a sitemap. It does not explicitly state when not to use it or alternatives, but the context of siblings makes it reasonable. It lacks explicit exclusions or alternatives.

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

indexnow_submitA

Submit changed URLs in bulk to IndexNow search engines: Bing, Yandex, Naver, Seznam, Yep; not Google. Needs an IndexNow key hosted on the site at https:///.txt (write; supports dryRun)

ParametersJSON Schema
NameRequiredDescriptionDefault
keyNoIndexNow key; defaults to SEO_MCP_INDEXNOW_KEY. The same key must be hosted on the site as a text file at https://<host>/<key>.txt (or at keyLocation) containing only the key
urlsYesChanged page URLs; one submission covers one host
dryRunNoIf true, report what would be submitted without notifying the endpoint
endpointNoIndexNow endpoint to notify; participating engines share submissionsapi.indexnow.org
keyLocationNoURL of the hosted key file when it is not https://<host>/<key>.txt

Output Schema

ParametersJSON Schema
NameRequiredDescription
hostYes
noteYes
dryRunNo
successYes
endpointYes
urlCountYes
statusCodeYes

TDQS

A4.3/5.0
Behavior4/5

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

No annotations are provided, so the description carries the full burden. It explicitly states the behavior: 'write' and 'supports dryRun', plus the prerequisite of a hosted key at a specific URL. It does not mention irreversibility or rate limits, but the write/dryRun disclosure is a meaningful safety signal.

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 a single dense sentence with no filler. It front-loads the action and then packs in the engine list, Google exclusion, key requirement, and write/dryRun mode without wasting words.

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 an output schema present and all parameters fully described in the schema, the description covers the essential operational context: purpose, target engines, key prerequisite, and dryRun capability. Nothing an agent needs to call it 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 description coverage is 100%, so the parameters are already documented. The tool description adds domain context beyond the schema by explaining the key must be hosted at a public URL and that the operation supports dryRun, which helps the agent understand preconditions and behavior.

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 uses a specific verb ('Submit') and resource ('changed URLs in bulk to IndexNow search engines'), enumerates the supported engines (Bing, Yandex, Naver, Seznam, Yep), and explicitly excludes Google. This clearly distinguishes it from sibling tools like submit_sitemap or request_recrawl.

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 description implies the usage scenario: submitting changed URLs in bulk to IndexNow engines and requiring a hosted key. However, it does not explicitly contrast this tool with siblings such as submit_sitemap or request_recrawl, nor does it state when not to use it beyond the Google exclusion.

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

inspect_urlA

Inspect a URL's Google index status, canonical selection, mobile usability, and rich results

ParametersJSON Schema
NameRequiredDescriptionDefault
siteUrlYesSearch Console property containing the inspected URL
inspectionUrlYesFully qualified URL to inspect

Output Schema

ParametersJSON Schema
NameRequiredDescription
siteUrlYes
indexStatusYes
richResultsYes
inspectionUrlYes
mobileUsabilityYes

TDQS

A3.6/5.0
Behavior3/5

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

With no annotations, the description carries the behavioral burden. 'Inspect' conveys a read-only operation and the listed facets clarify the scope, but it does not explicitly state that the URL is not modified or mention access requirements or timing caveats.

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 a single front-loaded sentence that lists the tool's scope with no filler or repetition. Every word adds meaning, and it is appropriately sized for a two-parameter tool.

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?

The tool is simple, both parameters are required and documented, and an output schema exists. The description sufficiently conveys what the tool inspects, but it could be more complete by addressing the rich sibling context and clarifying when not to use this tool.

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 siteUrl and inspectionUrl are already fully documented. The description adds no parameter-level detail, but none is needed at the baseline of 3.

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 uses a specific verb ('Inspect'), a concrete resource ('a URL'), and enumerates the inspection facets: Google index status, canonical selection, mobile usability, and rich results. An agent can tell what the tool does, but it does not explicitly differentiate it from related siblings like index_coverage or pagespeed.

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 description implies this is for per-URL Search Console diagnostics, but it never explicitly states when to use it versus alternatives. There are no exclusions, prerequisites, or named sibling tools, so the guidance stops at implication.

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

keyword_ideasA

Expand a seed with free Google Autocomplete suggestions and optionally cross-reference Search Console rankings; no extra API key needed

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoSearch Console lookback window in days
seedYesSeed keyword to expand
limitNoMaximum keyword ideas to return
countryNoAutocomplete country passed as gl
siteUrlNoOptional Search Console property used to identify queries already ranking
languageNoAutocomplete interface language passed as hlen
expansionsNoSuggestion expansion families to run beyond the bare seed

Output Schema

ParametersJSON Schema
NameRequiredDescription
seedYes
ideasYes
returnedYes
gscMatchedYes
totalFoundYes
crossReferencedYes
requestFailuresYes

TDQS

A4/5.0
Behavior3/5

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

No annotations are provided, so the description carries the burden. It discloses that it uses free Google Autocomplete suggestions and optionally cross-references Search Console rankings, and notes no extra API key is needed. However, it does not mention rate limits, whether the Search Console cross-reference requires an authenticated property, or what happens when siteUrl is invalid. These are meaningful gaps for a tool that combines two data sources.

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 sentence, front-loaded with the core action and the key differentiator (free, no extra API key). Every phrase earns its place: 'Expand a seed', 'free Google Autocomplete suggestions', 'optionally cross-reference Search Console rankings', and 'no extra API key needed' all convey essential information without waste.

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?

The tool has an output schema, so return values are covered. The description explains the core behavior and the optional Search Console integration. It is slightly incomplete regarding prerequisites for the Search Console cross-reference (e.g., whether siteUrl must be a verified property) and rate limits, but for a tool with 100% schema coverage and an output schema, this is a minor 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 the schema already documents all 7 parameters. The description adds the high-level concept of 'expand a seed' and 'cross-reference Search Console rankings', which maps to seed and siteUrl, but it does not add detail beyond the schema for parameters like days, limit, country, language, or expansions. Baseline 3 is correct.

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 ('Expand'), a resource ('seed'), and the mechanism ('free Google Autocomplete suggestions'), plus an optional cross-reference to Search Console rankings. It clearly distinguishes this from siblings like search_analytics or search_opportunities by focusing on keyword expansion rather than reporting or auditing.

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?

The description implies when to use it: when you need to expand a seed keyword into ideas, optionally using Search Console data. It does not explicitly name alternatives or state when not to use it, but the context of sibling tools (search_analytics, ctr_gaps, etc.) makes the use case reasonably clear. A 4 is appropriate because it gives clear context but lacks explicit exclusions.

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

list_propertiesA

List Google Search Console properties the service account can access, with permission levels

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYes
propertiesYes

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations, the description carries the burden of disclosing behavior. It makes clear this is a read/list operation scoped to the service account and that output includes permission levels, implying no side effects. It does not detail edge cases like empty results, but for a simple listing tool this is adequate.

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 conveys the resource, scope, and output contents without any filler. Every word contributes meaning.

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 zero-parameter listing tool with an output schema, this description is complete. The agent knows exactly what the tool returns and under whose access context, so no additional information is needed to invoke 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?

The tool has zero parameters, so there is nothing for the description to explain about inputs. The mention of permission levels adds useful context about the return data, and the baseline for a zero-parameter tool is 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 clearly states the action (list), the resource (Google Search Console properties), the scope (accessible to the service account), and the included detail (permission levels). This distinguishes it from sibling tools like list_sitemaps without needing to inspect schemas.

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?

The description provides clear context: this is the tool for discovering which GSC properties the service account can access and their permission levels. It does not explicitly name alternatives or exclusions, but among the siblings it is the only property-listing tool, so usage is unambiguous.

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

list_sitemapsA

List sitemaps submitted for a Google Search Console property

ParametersJSON Schema
NameRequiredDescriptionDefault
siteUrlYesSearch Console property

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYes
siteUrlYes
sitemapsYes

TDQS

A3.6/5.0
Behavior3/5

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

No annotations are provided, so the description carries the burden. The verb 'List' clearly signals a read-only operation, but nothing else is disclosed, such as whether siteUrl must exactly match the Search Console property format or whether pagination/limits apply. The disclosure is minimal but not misleading.

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 a single, focused sentence with no unnecessary words. It front-loads the action and object, making it immediately scannable and understandable.

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 one-parameter read-only tool with an output schema, the description is nearly sufficient. The only gaps are minor: it doesn't note the exact URL format for siteUrl or the relationship to submit_sitemap/delete_sitemap, but these are not necessary for a correct call and the output schema covers return values.

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% (siteUrl described as 'Search Console property'), and the tool description simply mirrors that same wording. No additional parameter semantics, formatting details, or usage constraints are provided, so the description adds no value beyond the schema.

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 ('List') and resource ('sitemaps submitted for a Google Search Console property'), with the qualifier 'submitted' narrowing scope precisely. This clearly distinguishes it from siblings such as submit_sitemap and delete_sitemap.

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 guidance is given on when to use this tool versus alternatives like submit_sitemap or delete_sitemap. The description does not mention any conditions, prerequisites, or exclusions, leaving the agent to infer usage from the tool name and sibling list.

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

list_snapshotsA

List the snapshot documents already in the snapshot directory, newest first: when each was taken, the window it covers, and how many properties, apps, packages and plugins it holds. This is what says whether there is an earlier snapshot to compare against and what to name as from and to; a file that does not parse is listed with its error rather than hidden; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum snapshots to return, newest first

Output Schema

ParametersJSON Schema
NameRequiredDescription
totalYes
directoryYes
snapshotsYes
truncatedYes

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden. It discloses that the operation is read-only, that results are newest first, and that unparseable files are listed with their error rather than hidden. This is strong, though it could also mention pagination behavior or result size limits.

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 sentences deliver a lot: the operation, ordering, included fields, workflow relevance, error handling, and safety. Every clause earns its place and the key behavior is front-loaded.

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 simple list tool with one optional parameter and a full output schema, the description is complete. It explains sorting, error visibility, read-only behavior, and how the output feeds into the broader snapshot workflow.

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?

The only parameter, limit, is fully documented in the schema with a default, bounds, and description. The tool description does not add further parameter details, but since schema coverage is 100%, the baseline of 3 is 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 begins with a specific verb and resource — 'List the snapshot documents already in the snapshot directory' — and even specifies ordering and content. It also differentiates from the sibling compare_snapshots by explaining this tool is what determines whether an earlier snapshot exists and what from/to values to use.

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 workflow context: use this to see what snapshots exist, check for an earlier snapshot, and decide the from/to names for comparison. It does not explicitly name alternatives or say 'use compare_snapshots instead', but the role is clear enough from the comparison-oriented sentence.

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

pagespeedB

Run PageSpeed Insights for field Core Web Vitals, Lighthouse scores, and top opportunities

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesPublic page URL to analyze
apiKeyNoOptional PageSpeed Insights API key; defaults to SEO_MCP_PAGESPEED_KEY
categoryNoLighthouse categories to run
strategyNoLighthouse device strategymobile

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlYes
scoresYes
strategyYes
fieldDataYes
opportunitiesYes

TDQS

B3.2/5.0
Behavior2/5

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

No annotations are present, so the description carries full responsibility for disclosing behavioral traits. It does not mention that this is a network call, that the URL must be public, that it may be slow or rate-limited, or any other side effects. This is a significant gap for a tool that invokes a remote API.

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 a single, front-loaded sentence with zero wasted words. It efficiently communicates the tool's core action and output focus.

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

Completeness2/5

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

Given the tool's complexity (4 params, external API call, output schema present) and the many sibling tools that overlap (crux_field_data, seo_audit, audit_site), the description is too thin. It lacks guidance on when to use it, what field vs. lab distinction means, and any operational caveats.

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 schema already documents all parameters (url, apiKey, category, strategy) with descriptions and defaults. The description adds no additional parameter meaning, so the baseline score of 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 ('Run'), resource ('PageSpeed Insights'), and outputs ('field Core Web Vitals, Lighthouse scores, and top opportunities'). This clearly distinguishes it from siblings like crux_field_data (field-only) or seo_audit (broader audit), even 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 Guidelines2/5

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

No guidance is given about when to choose this tool over the many similar siblings (e.g., crux_field_data, seo_audit, audit_site). The description simply states what it does, leaving the agent to infer use cases and differentiation.

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

play_store_statsA

Read Google Play bulk reports for an app: active device installs and store-listing visitors and acquisitions by traffic source. installsDimension picks which installs breakdown is read (overview, country, language, device, os_version, carrier or app_version), include adds the ratings, crashes and reviews report families, and startDate with endDate reads every month the window touches instead of the single month in month. Reads the reporting bucket named by SEO_MCP_PLAY_BUCKET; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
monthNoReport month as YYYYMM; defaults to the current UTC month. Ignored when startDate and endDate are given
endDateNoWindow end in YYYY-MM-DD
includeNoExtra report families to read. Missing files are normal: Google emits a report only when there is something to report
startDateNoWindow start in YYYY-MM-DD. With endDate, reads every month the window touches and filters rows to it
packageNameYesAndroid package name, e.g. app.getpsst
crashesDimensionNoDimension for the crashes reportapp_version
ratingsDimensionNoDimension for the ratings reportcountry
installsDimensionNoWhich installs report to read. overview is undocumented by Google but present in real buckets; the others are the documented breakdownsoverview
storePerformanceTotalsNoRead the total_ variant instead. It is a different report, not a rollup of the same one: it carries acquisitions only, with no visitors and no conversion rate, and for some apps it covers far fewer dates and attributes every acquisition to a placeholder source
storePerformanceDimensionNoWhich store performance breakdown to readtraffic_source

Output Schema

ParametersJSON Schema
NameRequiredDescription
monthYes
notesYes
windowYes
crashesYes
ratingsYes
reviewsYes
monthsReadYes
packageNameYes
datesPresentYes
installsLatestYes
trafficSourcesYes
lastDatePresentYes
hasPlaySearchRowsYes
installsDimensionYes
activeDeviceInstallsYes
installsWindowTotalsYes
installsZeroThroughoutYes
storePerformanceTotalsYes
storePerformanceDimensionYes

TDQS

A3.9/5.0
Behavior4/5

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

With no annotations provided, the description carries the safety burden and does disclose 'read-only' and the backing bucket (SEO_MCP_PLAY_BUCKET), both beyond what the schema states. The deeper quirks — missing files being normal and storePerformanceTotals not being a rollup — are documented in parameter descriptions rather than the tool description, so disclosure is strong but not maximal.

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 with purpose front-loaded and config/safety placed last; every sentence earns its place for a 10-parameter tool. The middle sentence is a long run-on covering several parameters, which slightly hurts scannability but remains efficient overall.

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 10-parameter tool with no annotations, the description covers purpose, key parameter interactions, the backing bucket, and safety in three sentences, while the 100%-coverage schema and output schema carry the remaining parameter and return-value documentation. It is missing explicit sibling differentiation and operational details such as rate limits or auth, which would push it to a 5.

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 baseline is 3. The description restates parameter behavior (installsDimension breakdown values, include report families, startDate/endDate window semantics) that the schema already documents in equal or greater detail, adding little new meaning beyond a compact framing.

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 — 'Read Google Play bulk reports for an app' — and enumerates the exact data families (active device installs, store-listing visitors, acquisitions by traffic source). The explicit 'Google Play' framing sets it apart from the app_store_* Apple siblings and from play_vitals, so an agent can pick it 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 Guidelines3/5

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

The data domain is precise enough that for Play installs or store-listing metrics this is the obvious tool, but the description never states when not to use it or names alternatives such as play_vitals. Usage context is implied from the domain wording rather than explicitly guided.

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

play_vitalsA

Read Android vitals from the Play Developer Reporting API: crash rate, ANR rate, error counts and startup metrics, daily or hourly, with optional breakdowns. Reports how fresh the data actually is. Carries no acquisition or conversion data; use play_store_stats for that. Read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoHow many days back to query
pageSizeNoRows per metric set
dimensionsNoBreakdown dimensions such as versionCode or countryCode
metricSetsNoWhich Android vitals metric sets to query
includeRowsNoInclude every raw row as well as the counts; off by default so a summary call stays small
packageNameYesAndroid package name
aggregationPeriodNoDAILY is reported in America/Los_Angeles, HOURLY in UTCDAILY

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
notesYes
metricSetsYes
packageNameYes
aggregationPeriodYes

TDQS

A4.1/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden. It states 'Read-only,' which is a key behavioral trait, and mentions that it reports data freshness, giving extra context. It does not detail rate limits, pagination, or error handling, but the read-only nature and freshness reporting are valuable disclosures that go beyond 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?

The description is three sentences, each serving a purpose: stating the core function, highlighting a unique feature (freshness), and providing an exclusion. It is concise and well-organized, though the freshness statement could be integrated more tightly, but it is still efficient.

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?

The tool is complex (7 parameters, output schema), but the description covers purpose, key behavioral aspects (read-only, freshness), and a sibling alternative. It does not explicitly state when to use it (beyond data type), but given the schema and output schema exist, the essential information is present. The lack of explicit 'use when' guidance is a minor gap, making it a 4 rather than a 5.

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 every parameter is already documented. The description adds minimal parameter-specific value—it mentions 'daily or hourly' (aggregationPeriod) and 'optional breakdowns' (dimensions) but does not elaborate beyond what the schema already states. Given the full schema coverage, the baseline of 3 is appropriate; the description supplements slightly but does not carry much extra semantic load.

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 clearly states the tool reads Android vitals (crash rate, ANR rate, error counts, startup metrics) from the Play Developer Reporting API, with temporal granularity and breakdown options. It explicitly names the data domain and scope, distinguishing it from sibling tools like play_store_stats. The verb 'read' and resource 'Android vitals' are specific.

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?

The description explicitly says it carries no acquisition or conversion data and directs users to play_store_stats for that, providing a clear exclusion and alternative. However, it does not offer broader 'when to use' guidance beyond the data-type distinction, and it does not mention other potential alternatives for metrics not covered, though that is sufficient.

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

query_cannibalizationA

Find queries served by multiple pages to prioritize consolidation and internal-linking decisions

ParametersJSON Schema
NameRequiredDescriptionDefault
endDateNoEnd date in YYYY-MM-DD; defaults to today
siteUrlYesSearch Console property to analyze
startDateNoStart date in YYYY-MM-DD; defaults to the latest 28-day window
minImpressionsNoMinimum impressions per query-page row; defaults to 10

Output Schema

ParametersJSON Schema
NameRequiredDescription
groupsYesQueries with multiple ranking pages
windowYesAnalysis window
siteUrlYesSearch Console property analyzed
truncatedYesWhether Search Console held more than 5000 rows for this window, so the list was computed from the top rows only

TDQS

A3.5/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden. It does not disclose whether the operation is read-only, any data limits, or the nature of the results beyond finding queries. It lacks explicit statements about what the tool does not do or any side effects, which is a gap for a tool with no annotation safety profile.

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, focused sentence that front-loads the purpose and avoids redundancy. It is concise and every word contributes to the definition.

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?

The tool has an output schema, so return value documentation is not required. However, given the complexity of cannibalization analysis, the description is minimal and does not explain the conceptual basis (e.g., how queries are attributed to multiple pages) or any filtering logic beyond what schema parameters imply. It is adequate but not rich.

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 all four parameters. The description adds no extra meaning about parameter usage, formats, or relationships beyond what the schema provides, so the baseline of 3 is 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 clearly states the verb 'Find' and the resource 'queries served by multiple pages', with an explicit purpose ('prioritize consolidation and internal-linking decisions'). This distinguishes it from sibling tools like search_analytics or ctr_gaps by focusing on multi-page cannibalization.

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 description implies its use case (cannibalization analysis) but provides no explicit guidance on when to choose this over alternatives like ctr_gaps or search_opportunities. There is no mention of prerequisites or exclusion conditions, leaving the agent to infer applicability.

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

request_recrawlC

Inspect URLs' Google index status and resubmit the covering sitemap for the ones not indexed, the supported bulk recrawl nudge (write; supports dryRun)

ParametersJSON Schema
NameRequiredDescriptionDefault
urlsNoExplicit URLs to check; omit to read them from sitemapUrl
dryRunNoIf true, inspect and report without resubmitting the sitemap
maxUrlsNoMaximum sitemap URLs to inspect
siteUrlYesSearch Console property containing the URLs
feedpathNoSitemap to resubmit when unindexed URLs are found; defaults to sitemapUrl
sitemapUrlNoSitemap to read URLs from; also the default sitemap to resubmit
concurrencyNoConcurrent URL Inspection requests

Output Schema

ParametersJSON Schema
NameRequiredDescription
dryRunNo
failedYes
checkedYes
indexedYes
resultsYes
siteUrlYes
resubmitYes
truncatedYes
notIndexedYes
totalDiscoveredYes

TDQS

C2.9/5.0
Behavior3/5

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

No annotations are provided, so the description carries the behavioral disclosure burden. It does disclose that the operation is a write ('write'), supports dryRun, and only resubmits sitemaps for unindexed URLs. However, it omits permissions, rate limits, reversibility, and side effects beyond sitemap resubmission, which matters for a mutation tool.

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

Conciseness3/5

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

The description is a single sentence and gets the core action front-loaded, but the phrasing 'the supported bulk recrawl nudge (write; supports dryRun)' is awkward and creates a confusing comma splice. It is compact but not well structured, reducing clarity.

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

Completeness2/5

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

For a 7-parameter write tool with no annotations and a rich sibling set, the description is too thin. It lacks usage context, prerequisites, side-effect details, and alternative routes, especially relative to inspect_url and submit_sitemap. The output schema and parameter coverage help, but the description does not fully compensate for the missing operational context.

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 baseline is 3 even without parameter details in the description. The description adds minimal extra semantics by clarifying the 'covering sitemap' concept and dryRun, but it does not meaningfully elaborate on the seven parameters beyond what the schema already provides.

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: it inspects URLs' Google index status and resubmits the covering sitemap for unindexed URLs. It clearly conveys a bulk recrawl nudge that combines inspection and submission, which distinguishes it from sibling tools like inspect_url or submit_sitemap, though it does not name those alternatives explicitly.

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 choose this tool over siblings such as inspect_url, submit_sitemap, or index_coverage. The description implies usage for bulk re-indexing requests, but it never states conditions, exclusions, or alternatives, leaving the selection decision to the agent.

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

search_analyticsB

Query Google Search Console search analytics and return ranked clicks, impressions, CTR, and position

ParametersJSON Schema
NameRequiredDescriptionDefault
typeNoResult type. discover is the Discover feed and googleNews is the Google News app and news.google.com, not the News tab in Search. Both support fewer dimensions than web: neither reports a query dimension
endDateNoEnd date in YYYY-MM-DD; defaults to today
siteUrlYesSearch Console property, such as https://example.com/ or sc-domain:example.com
rowLimitNoMaximum rows to return
startRowNoZero-based row to start from, for paging through a large result
dataStateNofull = finalized data (default, ~2-3 day lag); all = include recent partial data
startDateNoStart date in YYYY-MM-DD; defaults to 28 days ago
dimensionsNoDimensions used to group results
maxTableRowsNoCap rows shown in the text table; structured rows are always complete. 0 = summary only.
aggregationTypeNoHow Search Console aggregates rows
dimensionFilterGroupsNoSearch Console dimension filters

Output Schema

ParametersJSON Schema
NameRequiredDescription
rowsYes
endDateYes
siteUrlYes
rowCountYes
startRowYes
startDateYes
truncatedYesMore rows follow this page. False does not mean the result is complete: Search Console returns top rows subject to its own internal limits
dimensionsYes
firstIncompleteDateNo

TDQS

B3.1/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It only states a read-style query and the metrics returned, without mentioning pagination, default row limits, data-state lag, output ordering behavior, or other caveats beyond the single word 'ranked'.

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 that names the action, resource, and return metrics with no redundant words or filler. It is appropriately sized for the information it conveys.

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?

The rich input schema and output schema cover the mechanics of invocation well, and the core purpose is clear. However, with no annotations and no usage guidance amid many sibling analytics tools, the definition lacks routing and behavioral context, leaving it adequate but not fully complete.

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%, with detailed documentation for all 11 parameters, including defaults, enums, patterns, and constraints. The description itself adds no parameter-level detail, 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?

The description identifies a specific verb ('Query'), a specific resource ('Google Search Console search analytics'), and the returned metrics ('ranked clicks, impressions, CTR, and position'). It is unambiguous about what the tool does, but it does not explicitly distinguish itself from sibling tools like search_opportunities or compare_search_periods, so it falls 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 Guidelines2/5

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

There is no guidance about when to use this tool versus alternatives. The description does not mention exclusions, preferred contexts, or how this tool relates to siblings such as ctr_gaps or search_opportunities, leaving an agent to infer the intended use case.

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

search_opportunitiesA

Find queries ranking just off page 1 with high impressions, the highest-ROI keywords to improve

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum opportunities to return; defaults to 50
endDateNoEnd date in YYYY-MM-DD; defaults to today
siteUrlYesSearch Console property to analyze
startDateNoStart date in YYYY-MM-DD; defaults to the latest 28-day window
maxPositionNoHighest average position to include; defaults to 20
minPositionNoLowest average position to include; defaults to 5
minImpressionsNoMinimum impressions required; defaults to 10

Output Schema

ParametersJSON Schema
NameRequiredDescription
windowYesAnalysis window
siteUrlYesSearch Console property analyzed
truncatedYesWhether Search Console held more than 5000 rows for this window, so the list was computed from the top rows only
opportunitiesYesHighest-value striking-distance rows

TDQS

A3.8/5.0
Behavior3/5

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

With no annotations provided, the description must carry the burden of behavioral disclosure. The verb 'Find' implies a read-only analysis, but the description does not explicitly state that no data is mutated, nor does it clarify whether results are sorted by an ROI metric or merely filtered. It provides some behavioral context but leaves room for inference.

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 a single, front-loaded sentence with no fluff or repetition. It states the core purpose and selection criteria efficiently, making every word useful.

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?

All seven parameters are fully described in the schemaaca and there is an output schema, so the description does not need to explain return structure. The description adequately captures the tool's purpose and main criteria, though it omits explicit guidance on alternatives or sorting behavior, which would make it fully complete.

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 every parameter is already documented. The description adds general semantic context around position and impressions but does not map to specific parameters beyond that. Baseline 3 is appropriate since the schema handles parameter semantics.

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 clearly identifies the action ('Find queries') and the selection criteria ('ranking just off page 1 with high impressions'). It implicitly differentiates from siblings like search_analytics or keyword_ideas by focusing on opportunity-oriented filtering, though it never names an alternative.

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?

The description gives clear context for when to use the tool: when seeking high-impression queries that rank just off page 1 and could be improved. It does not explicitly mention when not to use it or point to alternatives, but the use case is well enough implied.

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

seo_auditA

Fetch and audit a web page's on-page SEO without Google credentials

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesPublic page URL to audit

Output Schema

ParametersJSON Schema
NameRequiredDescription
h1Yes
urlYes
langYes
linksYes
titleYes
imagesYes
issuesYes
twitterYes
viewportYes
canonicalYes
openGraphYes
wordCountYes
httpStatusYes
metaRobotsYes
schemaTypesYes
headingOutlineYes
metaDescriptionYes

TDQS

A4/5.0
Behavior3/5

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

No annotations are provided, so the description carries the burden. It discloses that the tool fetches and audits a page, and that no Google credentials are needed. However, it doesn't mention rate limits, whether the audit is synchronous, what happens with non-public or unreachable pages, or any side effects. For a read-only audit tool, this is adequate but not rich.

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 that states the action, resource, and key constraint. Every word earns its place; no filler or repetition of schema details.

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?

The tool has one parameter, a 100% schema description, and an output schema, so the description doesn't need to explain return values. The main missing context is behavioral details like timeout or error handling, but for a simple single-URL audit tool, the description is largely complete.

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 parameter 'url' is already described as 'Public page URL to audit'. The description adds the 'without Google credentials' context but doesn't add new parameter-level meaning beyond the schema. Baseline 3 is 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 uses a specific verb ('Fetch and audit') with a clear resource ('a web page's on-page SEO') and adds a key differentiator ('without Google credentials'). This distinguishes it from sibling tools like audit_site, inspect_url, and pagespeed, which require or imply different scopes or credential setups.

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?

The phrase 'without Google credentials' clearly signals when to use this tool over credential-requiring siblings like search_analytics or inspect_url. It doesn't explicitly name alternatives or state when not to use it, but the context is clear enough for an agent to route correctly.

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

server_versionA

Report which build of this server is answering, where it is running from, and whether it came out of an npx cache. Four values look like this one and are not: what npm calls latest, what the version range resolves to, what the plugin manifest declares, and what is actually running. Checking the command-line tool is not a substitute, since it is a separate process resolved separately. No credentials needed; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
nameYes
versionYesThe version of the build answering this call, which is not necessarily what npm calls latest, what the version range resolves to, or what the plugin manifest declares
npxCacheYesWhether this build is being served out of an npx cache, which reuses a build without re-resolving the version range and without erroring
installPathYesWhere this build is running from. An npx cache path is what distinguishes the release you expected from whatever npx already had
nodeVersionYes

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It states the operation is read-only, requires no credentials, and returns four values, and it explains the resolution context (npx cache, separate process). It does not describe the exact output format, but the presence of an output schema reduces the need for that detail.

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 compact and front-loaded with the core purpose, then adds the disambiguation and usage caveat. It is slightly dense and could be split into clearer sentences, but every sentence earns its place and there is no fluff.

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?

Given the tool has no parameters, an output schema exists, and the description covers purpose, disambiguation, credentials, and read-only behavior, the description is nearly complete. The only minor gap is not explicitly describing the output structure, but the output schema covers that.

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?

The tool has zero parameters, so there is no parameter semantics burden. The description adds meaningful context about what the returned values represent and what they are not, which is more than the empty schema provides. A baseline of 4 is appropriate for a no-parameter tool.

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 clearly states the tool reports which build of the server is answering, where it runs from, and whether it came from an npx cache. It distinguishes this from four similar-looking values (npm latest, version range resolution, plugin manifest, actually running) and from the command-line tool, so an agent can tell exactly what this tool does and what it does not do.

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?

The description explicitly warns that checking the command-line tool is not a substitute because it is a separate process resolved separately, and it clarifies that no credentials are needed and the operation is read-only. This gives clear when-to-use and when-not-to-use guidance, including an alternative that should not be used.

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

snapshotA

Capture four surfaces in one timestamped document: Search Console totals and top rows per property, App Store listings, Google Play installs and traffic, and WordPress.org stats. Core Web Vitals field data, Android vitals, App Store sales and App Store reviews are not captured. A surface that cannot be read is recorded as an error in place rather than omitted; list_snapshots names the documents already on disk to compare an earlier one against; read-only

ParametersJSON Schema
NameRequiredDescriptionDefault
appsNoApp Store apps, each a numeric app id or a bundle id
slugsNoWordPress.org plugin slugs
outPathNoFile name or path inside the snapshot directory (SEO_MCP_SNAPSHOT_DIR, default ~/.config/seo-mcp/snapshots); must end in .json, or pass auto to name the file after the moment it was taken. An existing file is not overwritten unless overwrite is true
packagesNoGoogle Play package names
platformNoApp Store platform for the app surfacesIOS
overwriteNoReplace an existing file at outPath; without it an existing file is left alone and reported
propertiesNoSearch Console properties to capture
windowDaysNoSearch Console window in days, ending today
storefrontsNoStorefront country codes for App Store ratings

Output Schema

ParametersJSON Schema
NameRequiredDescription
appsYes
slugsYes
windowYes
takenAtYes
packagesYes
writtenToNo
propertiesYes
windowDaysYes
surfacesWithErrorsYes

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral disclosure burden. It transparently states that a surface that cannot be read is recorded as an error in place rather than omitted, and it reveals that the tool writes timestamped documents on disk while labeling itself read-only. It does not cover authentication or rate limits, but the error-in-place and file-writing traits are the key behavioral disclosures and they are present.

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 dense but not padded: the first sentence establishes the composite scope, the second excludes whole data families, and the third covers error handling plus the sibling comparison tool and the read-only trait. Each sentence earns its place, though the third sentence is slightly run-on and packs two somewhat unrelated facts together.

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 9-parameter tool with no required parameters, an output schema, and full schema descriptions, the description covers what is captured, what is excluded, how failures are handled, and how to compare with previous snapshots. It does not offer a typical use case or explicit guidance to use single-surface siblings when only one surface is needed, but the combination of description, schema, and output schema is largely complete.

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 adds meaning by mapping each parameter array to a surface: properties to Search Console totals/top rows, apps to App Store listings, packages to Google Play installs/traffic, and slugs to WordPress.org stats. This contextualizes the 9 parameters beyond their individual schema descriptions. It does not restate defaults or constraints, which the schema already covers.

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 the verb ('Capture') and a clear resource ('four surfaces in one timestamped document'), then enumerates exactly which surfaces are included: Search Console totals and top rows per property, App Store listings, Google Play installs/traffic, and WordPress.org stats. It also explicitly lists excluded data families (Core Web Vitals, Android vitals, App Store sales and reviews), which distinguishes it sharply from siblings like crus_field_data, play_vitals, and app_store_sales.

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?

The description communicates when to use the tool by enumerating the four surfaces and explicitly stating what it does not capture, which lets an agent route to dedicated siblings for excluded data. It also points to list_snapshots for comparing against earlier documents. It does not explicitly name alternative single-surface tools for each included category, so the guidance is clear but not fully exhaustive.

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

submit_sitemapA

Submit a sitemap to Google Search Console and return its current state

ParametersJSON Schema
NameRequiredDescriptionDefault
dryRunNoIf true, report what would be submitted without writing to Search Console
siteUrlYesSearch Console property
feedpathYesAbsolute URL of the sitemap to submit

Output Schema

ParametersJSON Schema
NameRequiredDescription
dryRunNo
siteUrlYes
sitemapYes
successYes
feedpathYes
stateRefreshErrorYes

TDQS

A3.7/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It only states that it submits and returns the state, without mentioning side effects, permissions, or the meaning of the dryRun parameter. It also fails to clarify whether this is a write operation or if it can overwrite existing sitemaps.

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 a single, front-loaded sentence with no filler. It conveys the action and outcome efficiently.

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?

The presence of an output schema and full parameter coverage means return values and inputs are documented. However, the description lacks behavioral transparency and usage guidance, which are needed for a tool with no annotations, leaving some gaps for an agent deciding when and how to use it.

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?

The input schema covers all parameters with descriptions (100% coverage), so the baseline is 3. The description adds no parameter-specific guidance beyond what the schema already provides.

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 clearly states a specific verb ('Submit'), a resource ('sitemap'), and a destination ('Google Search Console'), and mentions it returns the current state. This distinguishes it from siblings like delete_sitemap or list_sitemaps.

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?

The description provides clear context that this tool is for submitting sitemaps, but it does not explicitly mention alternatives or when to prefer this over related tools like request_recrawl or indexnow_submit. There are no exclusions, so it is not misleading, but guidance is limited.

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

wporg_pluginA

Look up a WordPress.org plugin's install base, downloads, ratings, and support stats by slug; public API, no credentials or API key needed

ParametersJSON Schema
NameRequiredDescriptionDefault
slugYesWordPress.org plugin slug, e.g. akismet
downloadDaysNoDays of daily download history to fetch; 0 skips it
includeVersionDistributionNoAlso fetch the share of active installs on each plugin version

Output Schema

ParametersJSON Schema
NameRequiredDescription
nameYes
slugYes
tagsYes
addedYes
notesYes
ratingYes
testedYes
ratingsYes
versionYes
requiresYes
downloadedYes
numRatingsYes
lastUpdatedYes
requiresPhpYes
downloadLinkYes
versionCountYes
activeInstallsYes
dailyDownloadsYes
supportThreadsYes
downloadSummaryYes
possiblyLaggingYes
versionDistributionYes
supportThreadsResolvedYes
activeInstallsIsBucketedYes

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden. It discloses that the operation is a public API lookup requiring no credentials, which implies a safe read-only action. It does not mention rate limits or potential errors, but for a simple data retrieval tool, this level of disclosure is reasonably transparent.

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 a single sentence that front-loads the primary purpose and then adds the access condition. Every word earns its place, with no redundancy or filler.

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?

An output schema exists, so return values are documented. The description covers the tool's purpose, access method (public API, no credentials), and scope. All parameters are fully documented in the schema with defaults and constraints, so an agent has everything needed to call the tool correctly.

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 coverage is 100%, so the schema already documents all three parameters with descriptions, defaults, and constraints. The description adds no additional parameter-level meaning beyond stating the lookup is 'by slug', which matches the required parameter. Baseline 3 is 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 action 'Look up' with a precise resource 'WordPress.org plugin's install base, downloads, ratings, and support stats' and the key 'by slug'. It clearly distinguishes from all sibling tools, which are in SEO, app store, or ads domains, leaving no ambiguity about what this tool does.

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?

The description explicitly notes it uses a public API with no credentials or API key needed, providing a clear context for use. However, it does not offer explicit when-not-to-use guidance or name alternatives, though sibling tools are obviously unrelated, so the implied usage is clear.

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. 43 tool updatesv0.18.0
    • First observedads_ad_copy
    • First observedads_ads
    • First observedads_assets
    • First observedads_campaigns
    • First observedads_changes
    • First observedads_keyword_create
    • First observedads_keywords
    • First observedads_negatives
    • First observedads_negatives_update
    • First observedads_query
    • First observedads_search_terms
    • First observedads_update
    • First observedads_update_batch
    • First observedapp_store_discovery
    • First observedapp_store_listing
    • First observedapp_store_reviews
    • First observedapp_store_sales
    • First observedaudit_site
    • First observedcompare_search_periods
    • First observedcompare_snapshots
    • First observedcrux_field_data
    • First observedcrux_history
    • First observedctr_gaps
    • First observeddelete_sitemap
    • First observedindex_coverage
    • First observedindexnow_submit
    • First observedinspect_url
    • First observedkeyword_ideas
    • First observedlist_properties
    • First observedlist_sitemaps
    • First observedlist_snapshots
    • First observedpagespeed
    • First observedplay_store_stats
    • First observedplay_vitals
    • First observedquery_cannibalization
    • First observedrequest_recrawl
    • First observedsearch_analytics
    • First observedsearch_opportunities
    • First observedseo_audit
    • First observedserver_version
    • First observedsnapshot
    • First observedsubmit_sitemap
    • First observedwporg_plugin

TDQS

A3.5/5.0

Scored across 43 tools

Disambiguation3/5

Most tools target distinct surfaces (Search Console, App Store, Play, Ads, CRUX), and the detailed descriptions separate near neighbors like ctr_gaps and search_opportunities. However, clusters such as seo_audit/audit_site, ads_ads/ads_ad_copy, and the six search-analytics tools still create real selection risk, so the set is not fully unambiguous.

Naming Consistency4/5

The dominant pattern is snake_case verb_noun (list_sitemaps, submit_sitemap, ads_update, crux_field_data), and write tools consistently signal side effects. A notable minority uses noun-only or phrase names (keyword_ideas, search_opportunities, ctr_gaps, query_cannibalization, compare_search_periods), breaking the pattern enough to lower consistency.

Tool Count2/5

43 tools is far beyond the 3–15 sweet spot for a single server. The count is inflated by parallel surfaces (Search Console, App Store, Play, Ads, snapshots) and numerous analytics slice tools, which makes the server feel like a bundled suite rather than a focused console.

Completeness4/5

The set covers an unusually wide lifecycle: sitemap management, index inspection, search analytics, page audits, app-store/Play reads, ads reads and guarded writes, plus snapshot comparison. Gaps are minor—no Search Console property add/remove and no ad campaign or ad-group creation—but most workflows reach a terminal action.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    B
    maintenance
    SEO audit and Google Search Console MCP server with 23 tools. Search analytics, URL inspection, Indexing API, Core Web Vitals (CrUX), striking distance keywords, keyword cannibalization detection, branded query analysis, and automated site audits.
    30
    2
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    MCP server for querying Google Search Console data — search analytics, URL inspection, sitemap monitoring, and more — read-only tools for any MCP-compatible AI client.
    7
    Apache 2.0
  • A
    license
    B
    quality
    C
    maintenance
    MCP server that scrapes app data from Google Play and Apple App Store, providing tools for search, details, reviews, and similar apps.
    8
    15 npm
    MIT