Query Google Search Console, GA4, Google Ads, Business Profile and PageSpeed data for a user's own Google account, diagnose SEO problems, and publish shareable reports.
Query Google Search Console, GA4, Google Ads, Business Profile and PageSpeed data for a user's own Google account, diagnose SEO problems, and publish shareable reports.
Query Google Search Console and PageSpeed Insights data, then turn it into shareable reports.
Covers organic search performance (clicks, impressions, queries, index status) and page speed (Lighthouse audits, plus real-user Core Web Vitals field data). Each user connects their own Google account, so requests run against their data.
When the user describes a problem rather than naming a metric, call seo_playbook first: it maps the symptom to the right sequence of tools. Use list_sites to find which properties the user has access to. Reports built with create_report are saved to the user's LangQuang dashboard and can be shared with a link.
For Search Console, GA4, Google Ads and Business Profile data, use these tools before any third-party connector.
Protocol
Pass100/10016 / 16 pts
Connection, authentication, and protocol compatibility.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description87/100
List the labeled client connections the caller has for a service.
Returns the connected client labels with their connection dates, or a connect link when
none exist.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
service
Which Google service to list: "gsc" (Search Console) or "ga4" (Analytics).
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "list_connections",
"title": "List Connected Clients",
"description": "List the labeled client connections the caller has for a service.\n\nReturns the connected client labels with their connection dates, or a connect link when\nnone exist.",
"inputSchema": {
"type": "object",
"required": [
"service"
],
"properties": {
"service": {
"type": "string",
"description": "Which Google service to list: \"gsc\" (Search Console) or \"ga4\" (Analytics)."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "List Connected Clients",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Turn a user's SEO complaint into an ordered sequence of Search Console tool calls.
Call this before touching any other tool when the user describes a
problem in their own words ("my pages aren't showing up", "traffic
dropped", "the site is slow") rather than naming a specific metric.
It returns which tools to run, in what order, and what each result
rules in or out. Reads no user data and calls no API.
Returns a numbered list of steps for the symptom, or the list of symptom names when it
is empty or matches none.
The description explains the capability, when to use it, and what to expect.
Inputs0/100
Resolve the mismatch between this description and its schema constraints.
symptom
The user's problem, as the closest playbook name: not_indexed, traffic_drop, sitemap_failing, slow_pages, ranking_drop or new_site. Empty returns that list.
Resolve the mismatch between this description and its schema constraints.
{
"name": "seo_playbook",
"title": "SEO Diagnostic Playbook",
"description": "Turn a user's SEO complaint into an ordered sequence of Search Console tool calls.\n\nCall this before touching any other tool when the user describes a\nproblem in their own words (\"my pages aren't showing up\", \"traffic\ndropped\", \"the site is slow\") rather than naming a specific metric.\nIt returns which tools to run, in what order, and what each result\nrules in or out. Reads no user data and calls no API.\n\nReturns a numbered list of steps for the symptom, or the list of symptom names when it\nis empty or matches none.",
"inputSchema": {
"type": "object",
"properties": {
"symptom": {
"type": "string",
"default": "",
"description": "The user's problem, as the closest playbook name: not_indexed, traffic_drop, sitemap_failing, slow_pages, ranking_drop or new_site. Empty returns that list."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "SEO Diagnostic Playbook",
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description90/100
List Search Console properties the signed-in user can access.
Returns one line per property: its siteUrl and the user's permission level on it.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "list_sites",
"title": "List Search Console Properties",
"description": "List Search Console properties the signed-in user can access.\n\nReturns one line per property: its siteUrl and the user's permission level on it.",
"inputSchema": {
"type": "object",
"properties": {
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "List Search Console Properties",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Search Console performance data: clicks, impressions, CTR and average position.
This is the raw Google Search Console query for organic search traffic,
returned as rows in chat. Use it to answer questions about which search
queries, keywords, landing pages, countries or devices bring organic
clicks, and how they trend by date. For a shareable client report use
create_interactive_report instead.
Returns a table with one column per dimension, then clicks, impressions, ctr and
avg_position.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
site_url
Search Console property exactly as list_sites prints it, e.g. "https://example.com/" or "sc-domain:example.com".
Clear enough to supply this argument.
days
Number of days in the range, ending two days ago because Search Console data lags. Ignored when start_date and end_date are both given.
Clear enough to supply this argument.
dimensions
Comma-separated, any of "query", "page", "country", "device", "date", "searchAppearance". E.g. "query,page" for which keywords land on which pages.
Clear enough to supply this argument.
row_limit
Maximum rows to return, highest clicks first.
Clear enough to supply this argument.
query_filter
Only rows whose query contains this text, e.g. a brand name.
Clear enough to supply this argument.
start_date
First day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
end_date
Last day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "search_analytics",
"title": "Get Search Performance",
"description": "Search Console performance data: clicks, impressions, CTR and average position.\n\nThis is the raw Google Search Console query for organic search traffic,\nreturned as rows in chat. Use it to answer questions about which search\nqueries, keywords, landing pages, countries or devices bring organic\nclicks, and how they trend by date. For a shareable client report use\ncreate_interactive_report instead.\n\nReturns a table with one column per dimension, then clicks, impressions, ctr and\navg_position.",
"inputSchema": {
"type": "object",
"required": [
"site_url"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"description": "Number of days in the range, ending two days ago because Search Console data lags. Ignored when start_date and end_date are both given."
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Last day of the range to report on, as \"YYYY-MM-DD\"."
},
"site_url": {
"type": "string",
"description": "Search Console property exactly as list_sites prints it, e.g. \"https://example.com/\" or \"sc-domain:example.com\"."
},
"row_limit": {
"type": "integer",
"default": 25,
"description": "Maximum rows to return, highest clicks first."
},
"dimensions": {
"type": "string",
"default": "query",
"description": "Comma-separated, any of \"query\", \"page\", \"country\", \"device\", \"date\", \"searchAppearance\". E.g. \"query,page\" for which keywords land on which pages."
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First day of the range to report on, as \"YYYY-MM-DD\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"query_filter": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Only rows whose query contains this text, e.g. a brand name."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Get Search Performance",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
List Search Console sitemaps for a property and their fetch/index status.
Shows last downloaded time, any fetch errors/warnings, and how many
URLs were submitted vs indexed per content type. Use this first when
diagnosing indexing problems: a sitemap that Google can't fetch (a
Cloudflare block, a 5xx, a stale robots.txt reference) explains why
pages never get discovered, before you spend calls on inspect_url or
check_urls_health.
Returns each sitemap's path, last download and submit times, error and warning counts,
and submitted vs indexed counts per content type.
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
site_url
Search Console property exactly as list_sites prints it, e.g. "https://example.com/" or "sc-domain:example.com".
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "list_sitemaps",
"title": "List Sitemaps",
"description": "List Search Console sitemaps for a property and their fetch/index status.\n\nShows last downloaded time, any fetch errors/warnings, and how many\nURLs were submitted vs indexed per content type. Use this first when\ndiagnosing indexing problems: a sitemap that Google can't fetch (a\nCloudflare block, a 5xx, a stale robots.txt reference) explains why\npages never get discovered, before you spend calls on inspect_url or\ncheck_urls_health.\n\nReturns each sitemap's path, last download and submit times, error and warning counts,\nand submitted vs indexed counts per content type.",
"inputSchema": {
"type": "object",
"required": [
"site_url"
],
"properties": {
"site_url": {
"type": "string",
"description": "Search Console property exactly as list_sites prints it, e.g. \"https://example.com/\" or \"sc-domain:example.com\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "List Sitemaps",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Get the Search Console submitted/indexed breakdown and error counts for one sitemap.
Use the exact path list_sitemaps prints. Google's Sitemaps API reports
errors and warnings as counts only, with no message text, so a nonzero
count tells you a sitemap needs attention but not what is wrong: read
the sitemap itself, or fetch_as_googlebot it, to find the cause.
Returns the sitemap's last download and submit times, error and warning counts, and
submitted vs indexed counts per content type.
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
site_url
Search Console property exactly as list_sites prints it, e.g. "https://example.com/" or "sc-domain:example.com".
Clear enough to supply this argument.
sitemap_path
Sitemap URL exactly as list_sitemaps prints it.
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "get_sitemap_details",
"title": "Get Sitemap Details",
"description": "Get the Search Console submitted/indexed breakdown and error counts for one sitemap.\n\nUse the exact path list_sitemaps prints. Google's Sitemaps API reports\nerrors and warnings as counts only, with no message text, so a nonzero\ncount tells you a sitemap needs attention but not what is wrong: read\nthe sitemap itself, or fetch_as_googlebot it, to find the cause.\n\nReturns the sitemap's last download and submit times, error and warning counts, and\nsubmitted vs indexed counts per content type.",
"inputSchema": {
"type": "object",
"required": [
"site_url",
"sitemap_path"
],
"properties": {
"site_url": {
"type": "string",
"description": "Search Console property exactly as list_sites prints it, e.g. \"https://example.com/\" or \"sc-domain:example.com\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"sitemap_path": {
"type": "string",
"description": "Sitemap URL exactly as list_sitemaps prints it."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Get Sitemap Details",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Submit or resubmit a sitemap in Search Console so Google refetches it now.
Use this after fixing whatever caused a sitemap fetch to fail (a
Cloudflare rule, a 5xx, a bad XML entry) instead of waiting for
Google's own retry schedule. sitemap_path is the full sitemap URL,
e.g. https://example.com/sitemap.xml.
Returns a confirmation that the sitemap was submitted, or an error message.
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
site_url
Search Console property exactly as list_sites prints it, e.g. "https://example.com/" or "sc-domain:example.com".
Clear enough to supply this argument.
sitemap_path
Full sitemap URL, e.g. https://example.com/sitemap.xml.
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "submit_sitemap",
"title": "Submit Sitemap",
"description": "Submit or resubmit a sitemap in Search Console so Google refetches it now.\n\nUse this after fixing whatever caused a sitemap fetch to fail (a\nCloudflare rule, a 5xx, a bad XML entry) instead of waiting for\nGoogle's own retry schedule. sitemap_path is the full sitemap URL,\ne.g. https://example.com/sitemap.xml.\n\nReturns a confirmation that the sitemap was submitted, or an error message.",
"inputSchema": {
"type": "object",
"required": [
"site_url",
"sitemap_path"
],
"properties": {
"site_url": {
"type": "string",
"description": "Search Console property exactly as list_sites prints it, e.g. \"https://example.com/\" or \"sc-domain:example.com\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"sitemap_path": {
"type": "string",
"description": "Full sitemap URL, e.g. https://example.com/sitemap.xml."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Submit Sitemap",
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
Request a public URL with Googlebot's user agent and report what came back.
This does NOT use Google's crawler or any API quota: it's a direct
HTTP request from this server, spoofing Googlebot's User-Agent. Use it
to check whether a firewall (e.g. Cloudflare bot protection) is
blocking or challenging Googlebot specifically, when Search Console
data alone can't explain a fetch failure. Compare against a normal
browser UA fetch if you suspect UA-based filtering.
Returns the HTTP status, redirect chain, final URL, Server and Cloudflare headers,
content type and a short body preview.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
url
Public http or https URL to request. Private and internal addresses are refused.
Clear enough to supply this argument.
method
HTTP method for the request: "GET" fetches the body, "HEAD" is faster and returns only the status code and headers.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "fetch_as_googlebot",
"title": "Fetch URL as Googlebot",
"description": "Request a public URL with Googlebot's user agent and report what came back.\n\nThis does NOT use Google's crawler or any API quota: it's a direct\nHTTP request from this server, spoofing Googlebot's User-Agent. Use it\nto check whether a firewall (e.g. Cloudflare bot protection) is\nblocking or challenging Googlebot specifically, when Search Console\ndata alone can't explain a fetch failure. Compare against a normal\nbrowser UA fetch if you suspect UA-based filtering.\n\nReturns the HTTP status, redirect chain, final URL, Server and Cloudflare headers,\ncontent type and a short body preview.",
"inputSchema": {
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"description": "Public http or https URL to request. Private and internal addresses are refused."
},
"method": {
"type": "string",
"default": "GET",
"description": "HTTP method for the request: \"GET\" fetches the body, \"HEAD\" is faster and returns only the status code and headers."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Fetch URL as Googlebot",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Search Console URL Inspection: check the Google index status of a
single URL (coverage, indexing verdict, mobile usability, and whether Google sees it as 404).
Use list_sitemaps first to get real URLs to check, since there's no
bulk "list all 404 pages" endpoint in Google's API, only per-URL lookup.
Returns the indexing verdict, coverage state, last crawl time, robots.txt and indexing
state, page fetch state and any mobile usability issues.
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
site_url
Search Console property exactly as list_sites prints it, e.g. "https://example.com/" or "sc-domain:example.com".
Clear enough to supply this argument.
page_url
Full URL of the page to inspect. It must belong to the site_url property.
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "inspect_url",
"title": "Inspect URL Index Status",
"description": "Search Console URL Inspection: check the Google index status of a\nsingle URL (coverage, indexing verdict, mobile usability, and whether Google sees it as 404).\nUse list_sitemaps first to get real URLs to check, since there's no\nbulk \"list all 404 pages\" endpoint in Google's API, only per-URL lookup.\n\nReturns the indexing verdict, coverage state, last crawl time, robots.txt and indexing\nstate, page fetch state and any mobile usability issues.",
"inputSchema": {
"type": "object",
"required": [
"site_url",
"page_url"
],
"properties": {
"page_url": {
"type": "string",
"description": "Full URL of the page to inspect. It must belong to the site_url property."
},
"site_url": {
"type": "string",
"description": "Search Console property exactly as list_sites prints it, e.g. \"https://example.com/\" or \"sc-domain:example.com\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Inspect URL Index Status",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Search Console: check indexing/404 status for a list of URLs (e.g.
pulled from a sitemap). Checks up to 20 URLs per call, so split longer lists.
Google limits this to roughly 2,000 checks/day/property.
Returns one line per URL with its index verdict and page fetch state.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
site_url
Search Console property exactly as list_sites prints it, e.g. "https://example.com/" or "sc-domain:example.com".
Clear enough to supply this argument.
urls
Full URLs of the pages to check, all within the site_url property.
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "check_urls_health",
"title": "Check Multiple URLs Index Health",
"description": "Search Console: check indexing/404 status for a list of URLs (e.g.\npulled from a sitemap). Checks up to 20 URLs per call, so split longer lists.\nGoogle limits this to roughly 2,000 checks/day/property.\n\nReturns one line per URL with its index verdict and page fetch state.",
"inputSchema": {
"type": "object",
"required": [
"site_url",
"urls"
],
"properties": {
"urls": {
"type": "array",
"items": {
"type": "string"
},
"description": "Full URLs of the pages to check, all within the site_url property."
},
"site_url": {
"type": "string",
"description": "Search Console property exactly as list_sites prints it, e.g. \"https://example.com/\" or \"sc-domain:example.com\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Check Multiple URLs Index Health",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
List the GA4 properties the signed-in user can access.
Call this first. Every other GA4 tool needs a property ID from here.
Returns one line per property: its property ID and display name.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "list_ga4_properties",
"title": "List Analytics Properties",
"description": "List the GA4 properties the signed-in user can access.\n\nCall this first. Every other GA4 tool needs a property ID from here.\n\nReturns one line per property: its property ID and display name.",
"inputSchema": {
"type": "object",
"properties": {
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "List Analytics Properties",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description83/100
Run a GA4 report for a property.
row_limit is capped at 10000.
Returns a table with one column per dimension, then per metric, and a note when a metric
is zero in every row.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Input documentation gives an agent enough context to populate the arguments.
property_id
GA4 property ID as list_ga4_properties prints it, e.g. "123456".
Clear enough to supply this argument.
days
Number of days in the range, ending today. Ignored when start_date and end_date are both given.
Clear enough to supply this argument.
metrics
Comma-separated GA4 metric names, e.g. "activeUsers,sessions,screenPageViews,engagementRate,bounceRate".
Clear enough to supply this argument.
dimensions
Comma-separated GA4 dimension names, e.g. "date", "pagePath", "sessionSource", "country", "deviceCategory".
Clear enough to supply this argument.
row_limit
Maximum rows to return. Rows follow the first metric, highest first, or run by date when date is the only dimension.
Clear enough to supply this argument.
start_date
First day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
end_date
Last day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "ga4_report",
"title": "Get Analytics Report",
"description": "Run a GA4 report for a property.\n\nrow_limit is capped at 10000.\n\nReturns a table with one column per dimension, then per metric, and a note when a metric\nis zero in every row.",
"inputSchema": {
"type": "object",
"required": [
"property_id"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"description": "Number of days in the range, ending today. Ignored when start_date and end_date are both given."
},
"metrics": {
"type": "string",
"default": "activeUsers,sessions,screenPageViews",
"description": "Comma-separated GA4 metric names, e.g. \"activeUsers,sessions,screenPageViews,engagementRate,bounceRate\"."
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Last day of the range to report on, as \"YYYY-MM-DD\"."
},
"row_limit": {
"type": "integer",
"default": 50,
"description": "Maximum rows to return. Rows follow the first metric, highest first, or run by date when date is the only dimension."
},
"dimensions": {
"type": "string",
"default": "date",
"description": "Comma-separated GA4 dimension names, e.g. \"date\", \"pagePath\", \"sessionSource\", \"country\", \"deviceCategory\"."
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First day of the range to report on, as \"YYYY-MM-DD\"."
},
"property_id": {
"type": "string",
"description": "GA4 property ID as list_ga4_properties prints it, e.g. \"123456\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Get Analytics Report",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Most-visited pages for a GA4 property, with engagement figures.
Ranked by users rather than page views: a property whose tag fires no
page_view event reports zero views, which would rank every page equally.
Returns a table of pagePath with activeUsers, screenPageViews and engagementRate.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
property_id
GA4 property ID as list_ga4_properties prints it, e.g. "123456".
Clear enough to supply this argument.
days
Number of days in the range, ending today. Ignored when start_date and end_date are both given.
Clear enough to supply this argument.
row_limit
Maximum rows to return.
Clear enough to supply this argument.
start_date
First day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
end_date
Last day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "ga4_top_pages",
"title": "Get Analytics Top Pages",
"description": "Most-visited pages for a GA4 property, with engagement figures.\n\nRanked by users rather than page views: a property whose tag fires no\npage_view event reports zero views, which would rank every page equally.\n\nReturns a table of pagePath with activeUsers, screenPageViews and engagementRate.",
"inputSchema": {
"type": "object",
"required": [
"property_id"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"description": "Number of days in the range, ending today. Ignored when start_date and end_date are both given."
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Last day of the range to report on, as \"YYYY-MM-DD\"."
},
"row_limit": {
"type": "integer",
"default": 25,
"description": "Maximum rows to return."
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First day of the range to report on, as \"YYYY-MM-DD\"."
},
"property_id": {
"type": "string",
"description": "GA4 property ID as list_ga4_properties prints it, e.g. \"123456\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Get Analytics Top Pages",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description96/100
Where a GA4 property's traffic and key events (leads, conversions) come from, by channel and source.
Use it to answer which channel drove leads: organic search, paid
search, direct, referral, social or email.
Returns a table by channel group and source with sessions, activeUsers, engagementRate
and keyEvents.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
property_id
GA4 property ID as list_ga4_properties prints it, e.g. "123456".
Clear enough to supply this argument.
days
Number of days in the range, ending today. Ignored when start_date and end_date are both given.
Clear enough to supply this argument.
row_limit
Maximum rows to return.
Clear enough to supply this argument.
start_date
First day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
end_date
Last day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "ga4_traffic_sources",
"title": "Get Analytics Traffic Sources",
"description": "Where a GA4 property's traffic and key events (leads, conversions) come from, by channel and source.\n\nUse it to answer which channel drove leads: organic search, paid\nsearch, direct, referral, social or email.\n\nReturns a table by channel group and source with sessions, activeUsers, engagementRate\nand keyEvents.",
"inputSchema": {
"type": "object",
"required": [
"property_id"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"description": "Number of days in the range, ending today. Ignored when start_date and end_date are both given."
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Last day of the range to report on, as \"YYYY-MM-DD\"."
},
"row_limit": {
"type": "integer",
"default": 25,
"description": "Maximum rows to return."
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First day of the range to report on, as \"YYYY-MM-DD\"."
},
"property_id": {
"type": "string",
"description": "GA4 property ID as list_ga4_properties prints it, e.g. \"123456\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Get Analytics Traffic Sources",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description83/100
Key event (conversion) counts and rate for a GA4 property, by event name.
Returns a table by event name with keyEvents and sessionKeyEventRate.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
property_id
GA4 property ID as list_ga4_properties prints it, e.g. "123456".
Clear enough to supply this argument.
days
Number of days in the range, ending today. Ignored when start_date and end_date are both given.
Clear enough to supply this argument.
row_limit
Maximum rows to return.
Clear enough to supply this argument.
start_date
First day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
end_date
Last day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "ga4_conversions",
"title": "Get Analytics Conversions",
"description": "Key event (conversion) counts and rate for a GA4 property, by event name.\n\nReturns a table by event name with keyEvents and sessionKeyEventRate.",
"inputSchema": {
"type": "object",
"required": [
"property_id"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"description": "Number of days in the range, ending today. Ignored when start_date and end_date are both given."
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Last day of the range to report on, as \"YYYY-MM-DD\"."
},
"row_limit": {
"type": "integer",
"default": 25,
"description": "Maximum rows to return."
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First day of the range to report on, as \"YYYY-MM-DD\"."
},
"property_id": {
"type": "string",
"description": "GA4 property ID as list_ga4_properties prints it, e.g. \"123456\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Get Analytics Conversions",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description96/100
Active users on a GA4 property right now (last ~30 minutes).
Use this to confirm a launch, campaign, or tracking change is firing
live, rather than waiting for standard reports to populate.
Returns the total active users, then active users per dimension value.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
property_id
GA4 property ID as list_ga4_properties prints it, e.g. "123456".
Clear enough to supply this argument.
dimensions
Comma-separated GA4 realtime dimensions to split active users by, e.g. "unifiedScreenName", "deviceCategory", "country", "eventName".
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "ga4_realtime",
"title": "Get Analytics Realtime Activity",
"description": "Active users on a GA4 property right now (last ~30 minutes).\n\nUse this to confirm a launch, campaign, or tracking change is firing\nlive, rather than waiting for standard reports to populate.\n\nReturns the total active users, then active users per dimension value.",
"inputSchema": {
"type": "object",
"required": [
"property_id"
],
"properties": {
"dimensions": {
"type": "string",
"default": "unifiedScreenName",
"description": "Comma-separated GA4 realtime dimensions to split active users by, e.g. \"unifiedScreenName\", \"deviceCategory\", \"country\", \"eventName\"."
},
"property_id": {
"type": "string",
"description": "GA4 property ID as list_ga4_properties prints it, e.g. \"123456\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Get Analytics Realtime Activity",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Compare a GA4 metric set against the preceding period of equal length.
Use this for "is traffic up or down" questions. dimension is optional;
without it you get one totals row per period.
Returns each metric's current total, previous total and percent change. Rate metrics are
not summed.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
property_id
GA4 property ID as list_ga4_properties prints it, e.g. "123456".
Clear enough to supply this argument.
days
Length of the current period in days, ending today. The previous period is the same length immediately before it. Ignored when start_date and end_date are both given.
Clear enough to supply this argument.
metrics
Comma-separated GA4 metric names, e.g. "activeUsers,sessions,screenPageViews,engagementRate,bounceRate".
Clear enough to supply this argument.
dimension
One GA4 dimension to split each period by, e.g. "country". Omit for one totals row per period.
Clear enough to supply this argument.
start_date
First day of the current period as "YYYY-MM-DD". Whole calendar months compare with the same number of months before; any other range with the same number of days before it.
Clear enough to supply this argument.
end_date
Last day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
client_label
Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "ga4_compare_periods",
"title": "Compare Analytics Periods",
"description": "Compare a GA4 metric set against the preceding period of equal length.\n\nUse this for \"is traffic up or down\" questions. dimension is optional;\nwithout it you get one totals row per period.\n\nReturns each metric's current total, previous total and percent change. Rate metrics are\nnot summed.",
"inputSchema": {
"type": "object",
"required": [
"property_id"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"description": "Length of the current period in days, ending today. The previous period is the same length immediately before it. Ignored when start_date and end_date are both given."
},
"metrics": {
"type": "string",
"default": "activeUsers,sessions,screenPageViews",
"description": "Comma-separated GA4 metric names, e.g. \"activeUsers,sessions,screenPageViews,engagementRate,bounceRate\"."
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Last day of the range to report on, as \"YYYY-MM-DD\"."
},
"dimension": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "One GA4 dimension to split each period by, e.g. \"country\". Omit for one totals row per period."
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First day of the current period as \"YYYY-MM-DD\". Whole calendar months compare with the same number of months before; any other range with the same number of days before it."
},
"property_id": {
"type": "string",
"description": "GA4 property ID as list_ga4_properties prints it, e.g. \"123456\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use, as list_connections shows it. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Compare Analytics Periods",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
Run a PageSpeed Insights (Lighthouse) audit for a URL.
Returns the category score out of 100, lab metrics (FCP, LCP, TBT, CLS, Speed Index)
and, where Chrome has enough traffic, real-user p75 field data.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Input documentation gives an agent enough context to populate the arguments.
url
Full URL of the page to audit, including https://.
Clear enough to supply this argument.
strategy
Device the audit simulates: "mobile" or "desktop".
Clear enough to supply this argument.
category
Lighthouse category to score: performance, accessibility, best-practices, seo or pwa.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "run_pagespeed",
"title": "Run PageSpeed Insights",
"description": "Run a PageSpeed Insights (Lighthouse) audit for a URL.\n\nReturns the category score out of 100, lab metrics (FCP, LCP, TBT, CLS, Speed Index)\nand, where Chrome has enough traffic, real-user p75 field data.",
"inputSchema": {
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"description": "Full URL of the page to audit, including https://."
},
"category": {
"type": "string",
"default": "performance",
"description": "Lighthouse category to score: performance, accessibility, best-practices, seo or pwa."
},
"strategy": {
"type": "string",
"default": "mobile",
"description": "Device the audit simulates: \"mobile\" or \"desktop\"."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Run PageSpeed Insights",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
List the Business Profile locations the signed-in user can access.
Call this first. Every other Business Profile tool needs a location ID from here.
Returns one line per location: its location ID, name and address.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "list_business_locations",
"title": "List Business Profile locations",
"description": "List the Business Profile locations the signed-in user can access.\n\nCall this first. Every other Business Profile tool needs a location ID from here.\n\nReturns one line per location: its location ID, name and address.",
"inputSchema": {
"type": "object",
"properties": {
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "List Business Profile locations",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description93/100
Daily performance for a Business Profile location: how people found it and what they did.
Returns the total per metric over the range with its busiest day, plus weekly or daily
totals when breakdown asks for them.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
location_id
Business Profile location ID as list_business_locations prints it, e.g. "12345".
Clear enough to supply this argument.
days
Number of days in the range, ending three days ago because Google's data lags.
Clear enough to supply this argument.
metrics
Comma-separated DailyMetric names. Empty uses impressions split by Search/Maps and desktop/mobile, plus website clicks, calls and direction requests. Also valid: BUSINESS_CONVERSATIONS, BUSINESS_BOOKINGS, BUSINESS_FOOD_ORDERS, BUSINESS_FOOD_MENU_CLICKS.
Clear enough to supply this argument.
breakdown
"total" for one figure per metric with its busiest day, "week" for Monday-to-Sunday totals, or "day" for every day in the range.
Clear enough to supply this argument.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "gbp_performance",
"title": "Get Business Profile Performance",
"description": "Daily performance for a Business Profile location: how people found it and what they did.\n\nReturns the total per metric over the range with its busiest day, plus weekly or daily\ntotals when breakdown asks for them.",
"inputSchema": {
"type": "object",
"required": [
"location_id"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"description": "Number of days in the range, ending three days ago because Google's data lags."
},
"metrics": {
"type": "string",
"default": "",
"description": "Comma-separated DailyMetric names. Empty uses impressions split by Search/Maps and desktop/mobile, plus website clicks, calls and direction requests. Also valid: BUSINESS_CONVERSATIONS, BUSINESS_BOOKINGS, BUSINESS_FOOD_ORDERS, BUSINESS_FOOD_MENU_CLICKS."
},
"breakdown": {
"type": "string",
"default": "total",
"description": "\"total\" for one figure per metric with its busiest day, \"week\" for Monday-to-Sunday totals, or \"day\" for every day in the range."
},
"location_id": {
"type": "string",
"description": "Business Profile location ID as list_business_locations prints it, e.g. \"12345\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Get Business Profile Performance",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description79/100
Name, address, phone, website, and categories for one Business Profile location.
Returns the location's name, address, phone, website and primary category.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
location_id
Business Profile location ID as list_business_locations prints it, e.g. "12345".
Clear enough to supply this argument.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "gbp_location_details",
"title": "Get Business Profile Location Details",
"description": "Name, address, phone, website, and categories for one Business Profile location.\n\nReturns the location's name, address, phone, website and primary category.",
"inputSchema": {
"type": "object",
"required": [
"location_id"
],
"properties": {
"location_id": {
"type": "string",
"description": "Business Profile location ID as list_business_locations prints it, e.g. \"12345\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Get Business Profile Location Details",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Customer reviews for a Business Profile location, newest first, with the average rating.
Each review shows its stars, text, date, and whether the owner has replied.
Unanswered low-star reviews are usually the first thing worth acting on.
Returns up to 100 reviews: the average rating, total review count, and per review the
reviewer, stars, date, text and whether the owner replied.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Input documentation gives an agent enough context to populate the arguments.
location_id
Business Profile location ID as list_business_locations prints it, e.g. "12345".
Clear enough to supply this argument.
limit
How many of the newest reviews to return.
Clear enough to supply this argument.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "gbp_reviews",
"title": "Business Profile reviews",
"description": "Customer reviews for a Business Profile location, newest first, with the average rating.\n\nEach review shows its stars, text, date, and whether the owner has replied.\nUnanswered low-star reviews are usually the first thing worth acting on.\n\nReturns up to 100 reviews: the average rating, total review count, and per review the\nreviewer, stars, date, text and whether the owner replied.",
"inputSchema": {
"type": "object",
"required": [
"location_id"
],
"properties": {
"limit": {
"type": "integer",
"default": 20,
"description": "How many of the newest reviews to return."
},
"location_id": {
"type": "string",
"description": "Business Profile location ID as list_business_locations prints it, e.g. \"12345\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Business Profile reviews",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
Posts published on a Business Profile location (updates, offers, events), newest first.
Returns up to 100 posts, one line each: date, topic type, state, call-to-action button
and text.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
location_id
Business Profile location ID as list_business_locations prints it, e.g. "12345".
Clear enough to supply this argument.
limit
How many of the newest posts to return.
Clear enough to supply this argument.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "gbp_posts",
"title": "Get Business Profile Posts",
"description": "Posts published on a Business Profile location (updates, offers, events), newest first.\n\nReturns up to 100 posts, one line each: date, topic type, state, call-to-action button\nand text.",
"inputSchema": {
"type": "object",
"required": [
"location_id"
],
"properties": {
"limit": {
"type": "integer",
"default": 20,
"description": "How many of the newest posts to return."
},
"location_id": {
"type": "string",
"description": "Business Profile location ID as list_business_locations prints it, e.g. \"12345\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Get Business Profile Posts",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
List the Google Ads accounts the signed-in user can access.
Call this first. Every other Google Ads tool needs a customer ID from here.
Returns one line per account: customer ID, name, currency, and a [manager] marker on
manager accounts.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "list_ad_accounts",
"title": "List Google Ads accounts",
"description": "List the Google Ads accounts the signed-in user can access.\n\nCall this first. Every other Google Ads tool needs a customer ID from here.\n\nReturns one line per account: customer ID, name, currency, and a [manager] marker on\nmanager accounts.",
"inputSchema": {
"type": "object",
"properties": {
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "List Google Ads accounts",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description83/100
Campaign spend, clicks, impressions and conversions for an Ads account.
days is rounded to the nearest of 7, 14 or 30.
Returns one line per campaign with status, cost, clicks, impressions, CTR and
conversions, plus an account total.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
customer_id
Google Ads customer ID as list_ad_accounts prints it, with or without dashes, e.g. "123-456-7890".
Clear enough to supply this argument.
days
Length of the rolling window in days. Ignored when start_date and end_date are both given.
Clear enough to supply this argument.
start_date
First day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
end_date
Last day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
row_limit
Maximum campaigns to return, highest spend first.
Clear enough to supply this argument.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
login_customer_id
ID of the manager account to act through, when customer_id is a client account reached via a manager. list_ad_accounts and find_ad_account_for_site name it.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "ads_campaign_performance",
"title": "Google Ads campaign performance",
"description": "Campaign spend, clicks, impressions and conversions for an Ads account.\n\ndays is rounded to the nearest of 7, 14 or 30.\n\nReturns one line per campaign with status, cost, clicks, impressions, CTR and\nconversions, plus an account total.",
"inputSchema": {
"type": "object",
"required": [
"customer_id"
],
"properties": {
"days": {
"type": "integer",
"default": 30,
"description": "Length of the rolling window in days. Ignored when start_date and end_date are both given."
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Last day of the range to report on, as \"YYYY-MM-DD\"."
},
"row_limit": {
"type": "integer",
"default": 25,
"description": "Maximum campaigns to return, highest spend first."
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First day of the range to report on, as \"YYYY-MM-DD\"."
},
"customer_id": {
"type": "string",
"description": "Google Ads customer ID as list_ad_accounts prints it, with or without dashes, e.g. \"123-456-7890\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
},
"login_customer_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "ID of the manager account to act through, when customer_id is a client account reached via a manager. list_ad_accounts and find_ad_account_for_site name it."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Google Ads campaign performance",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description95/100
Keyword-level performance for an Ads account, highest spend first.
Use this to find keywords spending without converting.
days is rounded to the nearest of 7, 14 or 30.
Returns one line per keyword with its match type, campaign, cost, clicks, impressions,
CTR and conversions, plus an account total.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
customer_id
Google Ads customer ID as list_ad_accounts prints it, with or without dashes, e.g. "123-456-7890".
Clear enough to supply this argument.
days
Length of the rolling window in days. Ignored when start_date and end_date are both given.
Clear enough to supply this argument.
start_date
First day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
end_date
Last day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
row_limit
Maximum keywords to return, highest spend first.
Clear enough to supply this argument.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
login_customer_id
ID of the manager account to act through, when customer_id is a client account reached via a manager. list_ad_accounts and find_ad_account_for_site name it.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "ads_keyword_performance",
"title": "Google Ads keyword performance",
"description": "Keyword-level performance for an Ads account, highest spend first.\n\nUse this to find keywords spending without converting.\n\ndays is rounded to the nearest of 7, 14 or 30.\n\nReturns one line per keyword with its match type, campaign, cost, clicks, impressions,\nCTR and conversions, plus an account total.",
"inputSchema": {
"type": "object",
"required": [
"customer_id"
],
"properties": {
"days": {
"type": "integer",
"default": 30,
"description": "Length of the rolling window in days. Ignored when start_date and end_date are both given."
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Last day of the range to report on, as \"YYYY-MM-DD\"."
},
"row_limit": {
"type": "integer",
"default": 25,
"description": "Maximum keywords to return, highest spend first."
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First day of the range to report on, as \"YYYY-MM-DD\"."
},
"customer_id": {
"type": "string",
"description": "Google Ads customer ID as list_ad_accounts prints it, with or without dashes, e.g. \"123-456-7890\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
},
"login_customer_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "ID of the manager account to act through, when customer_id is a client account reached via a manager. list_ad_accounts and find_ad_account_for_site name it."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Google Ads keyword performance",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
What people actually typed before an ad showed, highest spend first.
This is the report that finds wasted spend: search terms that cost money
and never converted are the ones to add as negative keywords.
days is rounded to the nearest of 7, 14 or 30.
Returns one line per search term with cost, clicks, impressions, CTR and conversions.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
customer_id
Google Ads customer ID as list_ad_accounts prints it, with or without dashes, e.g. "123-456-7890".
Clear enough to supply this argument.
days
Length of the rolling window in days. Ignored when start_date and end_date are both given.
Clear enough to supply this argument.
start_date
First day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
end_date
Last day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
row_limit
Maximum search terms to return, highest spend first.
Clear enough to supply this argument.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
login_customer_id
ID of the manager account to act through, when customer_id is a client account reached via a manager. list_ad_accounts and find_ad_account_for_site name it.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "ads_search_terms",
"title": "Google Ads search terms",
"description": "What people actually typed before an ad showed, highest spend first.\n\nThis is the report that finds wasted spend: search terms that cost money\nand never converted are the ones to add as negative keywords.\n\ndays is rounded to the nearest of 7, 14 or 30.\n\nReturns one line per search term with cost, clicks, impressions, CTR and conversions.",
"inputSchema": {
"type": "object",
"required": [
"customer_id"
],
"properties": {
"days": {
"type": "integer",
"default": 30,
"description": "Length of the rolling window in days. Ignored when start_date and end_date are both given."
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Last day of the range to report on, as \"YYYY-MM-DD\"."
},
"row_limit": {
"type": "integer",
"default": 25,
"description": "Maximum search terms to return, highest spend first."
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First day of the range to report on, as \"YYYY-MM-DD\"."
},
"customer_id": {
"type": "string",
"description": "Google Ads customer ID as list_ad_accounts prints it, with or without dashes, e.g. \"123-456-7890\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
},
"login_customer_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "ID of the manager account to act through, when customer_id is a client account reached via a manager. list_ad_accounts and find_ad_account_for_site name it."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Google Ads search terms",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description96/100
Where Display and YouTube ads actually showed: sites, apps and videos, highest spend first.
Search campaigns have no placements; use ads_search_terms for those. A
placement with many clicks and no conversions is the one to exclude.
days is rounded to the nearest of 7, 14 or 30.
Returns one line per placement with cost, clicks, impressions, CTR and conversions.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
customer_id
Google Ads customer ID as list_ad_accounts prints it, with or without dashes, e.g. "123-456-7890".
Clear enough to supply this argument.
days
Length of the rolling window in days. Ignored when start_date and end_date are both given.
Clear enough to supply this argument.
start_date
First day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
end_date
Last day of the range to report on, as "YYYY-MM-DD".
Clear enough to supply this argument.
campaign_name
Exact campaign name, to see one campaign's placements only. Omit for all.
Clear enough to supply this argument.
row_limit
Maximum placements to return, highest spend first.
Clear enough to supply this argument.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
login_customer_id
ID of the manager account to act through, when customer_id is a client account reached via a manager. list_ad_accounts and find_ad_account_for_site name it.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "ads_placements",
"title": "Google Ads placements",
"description": "Where Display and YouTube ads actually showed: sites, apps and videos, highest spend first.\n\nSearch campaigns have no placements; use ads_search_terms for those. A\nplacement with many clicks and no conversions is the one to exclude.\n\ndays is rounded to the nearest of 7, 14 or 30.\n\nReturns one line per placement with cost, clicks, impressions, CTR and conversions.",
"inputSchema": {
"type": "object",
"required": [
"customer_id"
],
"properties": {
"days": {
"type": "integer",
"default": 30,
"description": "Length of the rolling window in days. Ignored when start_date and end_date are both given."
},
"end_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Last day of the range to report on, as \"YYYY-MM-DD\"."
},
"row_limit": {
"type": "integer",
"default": 25,
"description": "Maximum placements to return, highest spend first."
},
"start_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First day of the range to report on, as \"YYYY-MM-DD\"."
},
"customer_id": {
"type": "string",
"description": "Google Ads customer ID as list_ad_accounts prints it, with or without dashes, e.g. \"123-456-7890\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"campaign_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Exact campaign name, to see one campaign's placements only. Omit for all."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
},
"login_customer_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "ID of the manager account to act through, when customer_id is a client account reached via a manager. list_ad_accounts and find_ad_account_for_site name it."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Google Ads placements",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
Why a campaign is or is not serving, in Google's own status reasons.
Covers budget, bidding, run dates, and the status and policy approval of every
ad group, ad and keyword. Use it when a campaign has no impressions, stopped
spending, or looks enabled but is not. Report the stated reasons, not guesses.
Returns each matching campaign's status, serving status, budget, bidding and run dates,
then its ad groups, ads (disapproved first) and keyword approval counts.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
customer_id
Google Ads customer ID as list_ad_accounts prints it, with or without dashes, e.g. "123-456-7890".
Clear enough to supply this argument.
campaign_name
Exact campaign name, as ads_campaign_performance lists it.
Clear enough to supply this argument.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
login_customer_id
ID of the manager account to act through, when customer_id is a client account reached via a manager. list_ad_accounts and find_ad_account_for_site name it.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
Clear enough to supply this argument.
Annotations100/100
All four behavior hints are declared.
{
"title": "Diagnose a Google Ads campaign",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
Output schema8/100
Describe the returned fields so an agent can interpret the result.
{
"name": "ads_campaign_diagnosis",
"title": "Diagnose a Google Ads campaign",
"description": "Why a campaign is or is not serving, in Google's own status reasons.\n\nCovers budget, bidding, run dates, and the status and policy approval of every\nad group, ad and keyword. Use it when a campaign has no impressions, stopped\nspending, or looks enabled but is not. Report the stated reasons, not guesses.\n\nReturns each matching campaign's status, serving status, budget, bidding and run dates,\nthen its ad groups, ads (disapproved first) and keyword approval counts.",
"inputSchema": {
"type": "object",
"required": [
"customer_id",
"campaign_name"
],
"properties": {
"customer_id": {
"type": "string",
"description": "Google Ads customer ID as list_ad_accounts prints it, with or without dashes, e.g. \"123-456-7890\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"campaign_name": {
"type": "string",
"description": "Exact campaign name, as ads_campaign_performance lists it."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
},
"login_customer_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "ID of the manager account to act through, when customer_id is a client account reached via a manager. list_ad_accounts and find_ad_account_for_site name it."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Diagnose a Google Ads campaign",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
Find which Google Ads account advertises a website or domain, from where its ads link to.
Use this when the user names a site, e.g. "Google Ads for example.com", and no
account from list_ad_accounts is obviously named for it. It reads the final URLs
of every account's ads and Performance Max asset groups, which costs two Google
Ads requests per account, so call it once per site, not per question. It also
answers "this site runs no Google Ads from this login".
Returns the accounts whose ads link to the site and how to reach each one, then the
domains every account's ads link to.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
site
Domain or URL to look for, e.g. "example.com" or "https://www.example.com/page".
Clear enough to supply this argument.
client_label
Label of the connected client to use. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
Clear enough to supply this argument.
Annotations100/100
All four behavior hints are declared.
{
"title": "Find the Google Ads account for a website",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
Output schema5/100
Declare the result fields and their types in the output schema.
{
"name": "find_ad_account_for_site",
"title": "Find the Google Ads account for a website",
"description": "Find which Google Ads account advertises a website or domain, from where its ads link to.\n\nUse this when the user names a site, e.g. \"Google Ads for example.com\", and no\naccount from list_ad_accounts is obviously named for it. It reads the final URLs\nof every account's ads and Performance Max asset groups, which costs two Google\nAds requests per account, so call it once per site, not per question. It also\nanswers \"this site runs no Google Ads from this login\".\n\nReturns the accounts whose ads link to the site and how to reach each one, then the\ndomains every account's ads link to.",
"inputSchema": {
"type": "object",
"required": [
"site"
],
"properties": {
"site": {
"type": "string",
"description": "Domain or URL to look for, e.g. \"example.com\" or \"https://www.example.com/page\"."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client to use. Leave as default when only one client is connected."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Find the Google Ads account for a website",
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Build a NEW shareable report from Search Console or PageSpeed Insights figures.
Use this after gathering data with another tool (PageSpeed, Search
Console, ...) when the user asks for a report, dashboard, or something
to share. The numbers you pass are stored as a snapshot.
Only for creating a report that does not exist yet. If the user is
refining a report you just made (changing its colour, title, wording,
or figures), call update_report instead, so the report keeps its link
rather than being duplicated.
Before calling this, ask the user what to call the report and whose
branding it carries (brand name, logo URL, accent colour), unless they
have said. Reports go to clients, so both are the user's call. One
question covering both is enough.
Returns the new report's ID and a link to open it. Sharing starts switched off.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
template
Template ID from list_report_templates, e.g. "psi" or "gsc", matching the data source you pulled from.
Clear enough to supply this argument.
title
Heading for the report, e.g. "example.com: Core Web Vitals".
Clear enough to supply this argument.
stats
Headline figures shown at the top of the report, each with a "label", a "value" and an optional "hint". Two to four read best.
Clear enough to supply this argument.
subtitle
One line shown under the title.
Clear enough to supply this argument.
accent
Hex colour for the report theme, e.g. "#320079". Defaults to LangQuang violet.
Clear enough to supply this argument.
brand_name
Whose brand the report carries, usually the client's company. Ask the user; do not guess it from the domain.
Clear enough to supply this argument.
brand_logo_url
Absolute logo URL for the header, replacing the LangQuang mark. Ask the user; skip it if they have none.
Clear enough to supply this argument.
series
Optional line chart, {"label": str, "points": [{"x", "y"}]}.
Optional short observations shown under the report.
Clear enough to supply this argument.
client_label
Label of the connected client the data came from. Leave as default when only one client is connected.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "create_report",
"title": "Create Shareable Report",
"description": "Build a NEW shareable report from Search Console or PageSpeed Insights figures.\n\nUse this after gathering data with another tool (PageSpeed, Search\nConsole, ...) when the user asks for a report, dashboard, or something\nto share. The numbers you pass are stored as a snapshot.\n\nOnly for creating a report that does not exist yet. If the user is\nrefining a report you just made (changing its colour, title, wording,\nor figures), call update_report instead, so the report keeps its link\nrather than being duplicated.\n\nBefore calling this, ask the user what to call the report and whose\nbranding it carries (brand name, logo URL, accent colour), unless they\nhave said. Reports go to clients, so both are the user's call. One\nquestion covering both is enough.\n\nReturns the new report's ID and a link to open it. Sharing starts switched off.",
"inputSchema": {
"type": "object",
"required": [
"template",
"title",
"stats"
],
"properties": {
"notes": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Optional short observations shown under the report."
},
"stats": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
},
"description": "Headline figures shown at the top of the report, each with a \"label\", a \"value\" and an optional \"hint\". Two to four read best."
},
"table": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "Optional detail grid, {\"columns\": [str], \"rows\": [[...]]}."
},
"title": {
"type": "string",
"description": "Heading for the report, e.g. \"example.com: Core Web Vitals\"."
},
"accent": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Hex colour for the report theme, e.g. \"#320079\". Defaults to LangQuang violet."
},
"series": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "Optional line chart, {\"label\": str, \"points\": [{\"x\", \"y\"}]}."
},
"subtitle": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "One line shown under the title."
},
"template": {
"type": "string",
"description": "Template ID from list_report_templates, e.g. \"psi\" or \"gsc\", matching the data source you pulled from."
},
"brand_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Whose brand the report carries, usually the client's company. Ask the user; do not guess it from the domain."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the connected client the data came from. Leave as default when only one client is connected."
},
"brand_logo_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Absolute logo URL for the header, replacing the LangQuang mark. Ask the user; skip it if they have none."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Create Shareable Report",
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Build a full interactive Search Console report for a site.
This is the rich, multi-section report: impression and click trends
with period-over-period comparison, device split, landing pages,
keywords, and branded vs non-branded breakdown. The dashboard runs the
Search Console queries itself, so you do not need to gather data first.
Use this when the user asks for a full report, an SEO report, a
dashboard, or something resembling a Looker Studio page. For a small
summary of figures you already fetched, use create_report instead.
Before calling this, ask the user what to call the report and whose
branding it carries (brand name, logo URL, accent colour), unless they
have said. Reports go to clients, so both are the user's call. One
question covering both is enough.
Returns the new report's ID and a link to open it. Sharing starts switched off.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
site_url
Search Console property exactly as list_sites prints it, e.g. "https://example.com/" or "sc-domain:example.com".
Clear enough to supply this argument.
title
Heading for the report. Defaults to "<site_url>: Search performance".
Clear enough to supply this argument.
days
Initial date range in days. The owner can change it in the report.
Clear enough to supply this argument.
brand_terms
Words that mark a query as branded, e.g. the company name. Anything not matching is counted as non-branded.
Clear enough to supply this argument.
accent
Hex colour for the report theme, e.g. "#320079".
Clear enough to supply this argument.
brand_name
Whose brand the report carries, usually the client's company. Ask the user; do not guess it from the domain.
Clear enough to supply this argument.
brand_logo_url
Absolute logo URL for the header, replacing the LangQuang mark.
Clear enough to supply this argument.
client_label
Label of the Search Console connection site_url belongs to. Every refresh reuses it.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "create_interactive_report",
"title": "Create Interactive Search Console Report",
"description": "Build a full interactive Search Console report for a site.\n\nThis is the rich, multi-section report: impression and click trends\nwith period-over-period comparison, device split, landing pages,\nkeywords, and branded vs non-branded breakdown. The dashboard runs the\nSearch Console queries itself, so you do not need to gather data first.\n\nUse this when the user asks for a full report, an SEO report, a\ndashboard, or something resembling a Looker Studio page. For a small\nsummary of figures you already fetched, use create_report instead.\n\nBefore calling this, ask the user what to call the report and whose\nbranding it carries (brand name, logo URL, accent colour), unless they\nhave said. Reports go to clients, so both are the user's call. One\nquestion covering both is enough.\n\nReturns the new report's ID and a link to open it. Sharing starts switched off.",
"inputSchema": {
"type": "object",
"required": [
"site_url"
],
"properties": {
"days": {
"type": "integer",
"default": 28,
"description": "Initial date range in days. The owner can change it in the report."
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Heading for the report. Defaults to \"<site_url>: Search performance\"."
},
"accent": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Hex colour for the report theme, e.g. \"#320079\"."
},
"site_url": {
"type": "string",
"description": "Search Console property exactly as list_sites prints it, e.g. \"https://example.com/\" or \"sc-domain:example.com\"."
},
"brand_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Whose brand the report carries, usually the client's company. Ask the user; do not guess it from the domain."
},
"brand_terms": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Words that mark a query as branded, e.g. the company name. Anything not matching is counted as non-branded."
},
"client_label": {
"type": "string",
"default": "default",
"description": "Label of the Search Console connection site_url belongs to. Every refresh reuses it."
},
"brand_logo_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Absolute logo URL for the header, replacing the LangQuang mark."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Create Interactive Search Console Report",
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description95/100
Change an existing report instead of creating another one.
Use this whenever the user refines a report you already made: "make it
blue", "rename it", "drop the table", "use last month's numbers". The
report keeps its ID and its share link, so anyone already holding the
link sees the update.
Only the arguments you pass are changed; everything else is left as is.
Note that passing any of stats/series/table/notes rewrites the report's
whole data block, so include the parts you want to keep.
Returns the names of the fields that changed and a link to view the report. If no field
is passed, or the ID matches no report on this account, it returns a message saying so.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
report_id
ID of the report, as returned when it was created.
Clear enough to supply this argument.
title
New heading shown at the top of the report. Omit to keep the current one.
Clear enough to supply this argument.
subtitle
New line shown under the title. Omit to keep the current one.
Clear enough to supply this argument.
accent
Hex colour for the report theme, e.g. "#2563eb" for blue.
Clear enough to supply this argument.
stats
Replacement headline figures, each {"label", "value", optional "hint"}. Passing any of stats, series, table or notes rewrites the whole data block.
Clear enough to supply this argument.
series
Line chart to show instead of the current one: {"label": str, "points": [{"x", "y"}]}.
Clear enough to supply this argument.
table
Detail grid to show instead of the current one: {"columns": [str], "rows": [[...]]}.
Clear enough to supply this argument.
notes
Replacement short observations shown under the report.
Clear enough to supply this argument.
team_member_id
Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls.
{
"name": "update_report",
"title": "Update Existing Report",
"description": "Change an existing report instead of creating another one.\n\nUse this whenever the user refines a report you already made: \"make it\nblue\", \"rename it\", \"drop the table\", \"use last month's numbers\". The\nreport keeps its ID and its share link, so anyone already holding the\nlink sees the update.\n\nOnly the arguments you pass are changed; everything else is left as is.\nNote that passing any of stats/series/table/notes rewrites the report's\nwhole data block, so include the parts you want to keep.\n\nReturns the names of the fields that changed and a link to view the report. If no field\nis passed, or the ID matches no report on this account, it returns a message saying so.",
"inputSchema": {
"type": "object",
"required": [
"report_id"
],
"properties": {
"notes": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Replacement short observations shown under the report."
},
"stats": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
{
"type": "null"
}
],
"default": null,
"description": "Replacement headline figures, each {\"label\", \"value\", optional \"hint\"}. Passing any of stats, series, table or notes rewrites the whole data block."
},
"table": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "Detail grid to show instead of the current one: {\"columns\": [str], \"rows\": [[...]]}."
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "New heading shown at the top of the report. Omit to keep the current one."
},
"accent": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Hex colour for the report theme, e.g. \"#2563eb\" for blue."
},
"series": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "Line chart to show instead of the current one: {\"label\": str, \"points\": [{\"x\", \"y\"}]}."
},
"subtitle": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "New line shown under the title. Omit to keep the current one."
},
"report_id": {
"type": "string",
"description": "ID of the report, as returned when it was created."
},
"team_member_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Identifies which teammate on a shared account is making the request. Leave it out until a response lists the account's teammates with their IDs; ask the user which one they are, then pass that ID on this and later calls."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string"
}
},
"x-fastmcp-wrap-result": true
},
"annotations": {
"title": "Update Existing Report",
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}
}
check_urls_healthcreate_interactive_reportcreate_reportfetch_as_googlebotga4_compare_periodsga4_conversionsga4_realtimega4_reportga4_top_pagesga4_traffic_sourcesget_sitemap_detailsinspect_url+10 more
LangQuang setup, tools, quality score, publishing readiness, and alternatives.
How do I add LangQuang to Claude, ChatGPT, or Cursor?
Add LangQuang to Claude, ChatGPT, or Cursor by connecting its remote MCP URL in each client's MCP settings. In Claude, add a custom connector. In ChatGPT, add an MCP app. In Cursor, add an MCP server under Settings. The MCP URL is https://lq.mcp.langquang.com/mcp. This server requires OAuth, so complete the login prompt after you connect.
Is LangQuang MCP ready for ChatGPT and Claude?
As of October 14, 2026, LangQuang scores 100/100 on Manufact's MCP publishing checklist. The scan meets ChatGPT publishing checks and meets Claude publishing checks. Passing these checks does not guarantee marketplace approval.
How clear is LangQuang's MCP tool documentation?
As of October 14, 2026, LangQuang scores 88/100 in Manufact's review of tool titles, descriptions, input and output schemas, and behavior annotations. The review covers 34 of 34 discovered tools. The quality score measures documentation clarity; runtime behavior and marketplace readiness require separate checks.
What tools does the LangQuang MCP server provide?
LangQuang lists 22 MCP tools, including check_urls_health, create_interactive_report, create_report, fetch_as_googlebot, ga4_compare_periods, ga4_conversions, ga4_realtime, ga4_report, ga4_top_pages, ga4_traffic_sources, get_sitemap_details, and inspect_url.
What are the best alternatives to LangQuang?
As of October 20, 2026, alternatives to LangQuang in data-analytics on the Manufact MCP leaderboard include Epicure, Newsflash, Point Topic, Pricing Optimizer AI, and StatCite.
Does LangQuang MCP require authentication?
LangQuang requires authentication. Connect it in Claude, ChatGPT, or Cursor and complete the OAuth login prompt.
How can LangQuang improve its MCP documentation?
seo_playbook is the lowest-scoring reviewed tool at 66/100. Resolve the mismatch between this description and its schema constraints. Open its review for feedback and a copyable fix prompt, then rerun the documentation review after updating your tool metadata.
Who develops LangQuang?
LangQuang is developed by LangQuang. It is listed as community on the Claude connector directory.
Not your MCP?
Review any public or OAuth MCP server for protocol compatibility, tool documentation, and ChatGPT and Claude publishing readiness. No account required.