# RevenueScope: revenue-first analytics for your EC site

> Ask AI about your EC site's revenue by channel, RPS/AOV/CVR, search & AI traffic, budget split.

- name: io.github.toshihiroshishido/revenuescope-mcp
- version: 1.9.1
- connection class: unknown (unknown)
- trust: 64/100 flags: unreachable
- quality: 66/100 (needs work)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/io.github.toshihiroshishido%2Frevenuescope-mcp
- tools: https://api.protogrid.dev/v1/servers/io.github.toshihiroshishido%2Frevenuescope-mcp/tools

**Not classified yet.** The remote endpoints have not been probed successfully, or the listing has nothing to connect to.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "revenuescope-mcp": {
      "type": "http",
      "url": "https://mcp.revenuescope.jp/api/mcp"
    }
  }
}
```


## Trust

- hygiene: 100
- liveness: 0
- freshness: 85
- provenance: 90
- drivers: +repository +namespace-matches-repo +website -unreachable(5 failures) ~updated-85d-ago
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 66/100 (needs work)

### protocol: 75 (weight 25)

- warn `protocol.modern`: newest supported version is 2025-11-25; 2026-07-28 not supported, older versions are deprecated until 2027-07-28
- n/a `protocol.stateless`: only applies to 2026-07-28 servers
- pass `protocol.transport`: streamable HTTP
- n/a `protocol.list_ttl`: only applies to 2026-07-28 servers

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 79 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 7 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 10 of 10 tools declare readOnlyHint or destructiveHint
- fail `tools.directory_hints`: no tool declares all four of readOnlyHint, destructiveHint, idempotentHint and openWorldHint; missing: get_breakdown (destructiveHint, idempotentHint); list_sites (destructiveHint, idempotentHint); get_page_trend (destructiveHint, idempotentHint); …
- pass `tools.token_cost`: about 5,264 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 25 (weight 15)

- warn `stability.changes`: 50 tool changes in 30 days
- fail `stability.rug_pull`: 14 tools kept their name but changed most of their description in 30 days; review before trusting them

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 10, about 5,264 tokens to load them all
- tool set hash: dd101068e0ea8e9b278dfd04cfc7eb98
- tools last changed: 2026-10-11T19:21:35.408Z
- badge: [![protogrid quality](https://protogrid.dev/badge/io.github.toshihiroshishido/revenuescope-mcp.svg)](https://protogrid.dev/servers/io.github.toshihiroshishido/revenuescope-mcp)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-10-11 `get_content_actions` changed (description)
  - before: Return content action buckets and page evidence. By default the window length is N=7 days and GSC data is delayed by 3 days. To choose a window, pass start_date and end_date together: end_date must be today's date in Japan time, and N is end_date minus start_date (2-365 days; e.g. September 21 through September 28 sets N=7), so the pair describes a length ending today rather than the GSC source dates. The response separates `window` (actual JST GSC dates, inclusive) from `session_window` (sessions, revenue and AI metrics over N×24 hours ending at database statement time). `session_window` gives the relative start/end and duration; exact timestamps are unavailable because the RPC does not return its `now()` value. Search classifications, thresholds, bucket_summary, row prioritization, caveats and limits are included in the response. A page carries `title_change` when its title was rewritten within the last 8 weeks (detected from the titles the tracker recorded): do not recommend another title rewrite for it while it is tracked, and read a rank change since the rewrite as a before/after comparison, not proof of effect. The app's home screen takes such pages off its to-do list, but this tool keeps them and their order in `pages` and only adds the mark; `title_changes.status` is 'unavailable' when the marks could not be read. Revenue values (revenue_jpy, ai_revenue_jpy, expected_revenue_gain and the bucket_summary revenue_jpy) are null when revenue_status is 'unconfirmed': null means unverified, not 0 yen. site_id is optional when OAuth-authenticated. Google Search only; data lags 1-2 days.
  - after: Return content action buckets and page evidence. By default the window length is N=7 days and GSC data is delayed by 3 days. To choose a window, pass start_date and end_date together: end_date must be today's date in Japan time, and N is end_date minus start_date (2-365 days; e.g. September 21 through September 28 sets N=7), so the pair describes a length ending today rather than the GSC source dates. The response separates `window` (actual JST GSC dates, inclusive) from `session_window` (sessions, revenue and AI metrics over N×24 hours ending at database statement time). `session_window` gives the relative start/end and duration; exact timestamps are unavailable because the RPC does not return its `now()` value. Search classifications, thresholds, bucket_summary, row prioritization, caveats and limits are included in the response. A page carries `title_change` when its title was rewritten within the last 8 weeks (detected from the titles the tracker recorded): do not recommend another title rewrite for it while it is tracked, and read a rank change since the rewrite as a before/after comparison, not proof of effect. The app's home screen takes such pages off its to-do list, but this tool keeps them and their order in `pages` and only adds the mark; `title_changes.status` is 'unavailable' when the marks could not be read. Revenue values (revenue_jpy, ai_revenue_jpy, expected_revenue_gain and the bucket_summary revenue_jpy) are null when revenue_status is 'unconfirmed': null means unverified, not 0 yen. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. Google Search only; data lags 1-2 days.
- 2026-10-11 `get_page_trend` changed (description)
  - before: Return how ONE page's Google Search performance changed over time. Pass start_date and end_date together as inclusive JST dates; comparison dates are not supported. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) for the same periods as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site time zone), and year_to_date starts on January 1 of the year of that Saturday; preset cannot be combined with start_date or end_date, and `period.preset` echoes it. Omitting all of them preserves the current now-minus-30-days rolling window, which may touch 31 JST dates because GSC filters by date inclusively. Explicit dates are converted to JST day boundaries for GSC rows. `granularity` defaults to day for windows up to about 35 days and week for longer windows; pass it to override. Weeks run Sunday to Saturday and each weekly `date` is that week's Sunday; weeks at the edge of the period hold only the days inside it. Buckets without GSC rows are omitted. Google-search only; data lags 1-2 days. site_id is optional when OAuth-authenticated. For cross-page snapshots use get_breakdown(dimension='page'); for query trends use get_keyword_performance.
  - after: Return how ONE page's Google Search performance changed over time. Pass start_date and end_date together as inclusive JST dates; comparison dates are not supported. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) for the same periods as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site time zone), and year_to_date starts on January 1 of the year of that Saturday; preset cannot be combined with start_date or end_date, and `period.preset` echoes it. Omitting all of them preserves the current now-minus-30-days rolling window, which may touch 31 JST dates because GSC filters by date inclusively. Explicit dates are converted to JST day boundaries for GSC rows. `granularity` defaults to day for windows up to about 35 days and week for longer windows; pass it to override. Weeks run Sunday to Saturday and each weekly `date` is that week's Sunday; weeks at the edge of the period hold only the days inside it. Buckets without GSC rows are omitted. Google-search only; data lags 1-2 days. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. For cross-page snapshots use get_breakdown(dimension='page'); for query trends use get_keyword_performance.
- 2026-10-11 `get_ai_traffic` changed (description, outputSchema)
  - before: Return AI-assistant traffic using dashboard_ai_referred, a separate RPC from the AI channels of dashboard_channels that the search screen shows (for the screen's number, use the AI channel in get_breakdown(dimension='channel')). By default, mode='referred' uses the site's calendar month to date and compares with the prior month through the same calendar day (clamped to the prior month's last day). Pass start_date and end_date together for another inclusive calendar range in the site's analysis timezone; optionally pass compare_start_date and compare_end_date. If comparison dates are omitted, the immediately preceding equal-length range is used. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) instead of dates, for the same periods and comparison as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site timezone), the comparison is the same number of days directly before it, and year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date, end_date, compare_start_date or compare_end_date, and `period.preset` echoes it. mode='gaps' is STOPPED and returns only its stopped notice. site_id is optional when OAuth-authenticated. Scope is clicked citations only.
  - after: Return AI-assistant traffic using dashboard_ai_referred, a separate RPC from the AI channels of dashboard_channels that the search screen shows (for the screen's number, use the AI channel in get_breakdown(dimension='channel')). By default, mode='referred' uses the site's calendar month to date and compares with the prior month through the same calendar day (clamped to the prior month's last day). Pass start_date and end_date together for another inclusive calendar range in the site's analysis timezone; optionally pass compare_start_date and compare_end_date. If comparison dates are omitted, the immediately preceding equal-length range is used. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) instead of dates, for the same periods and comparison as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site timezone), the comparison is the same number of days directly before it, and year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date, end_date, compare_start_date or compare_end_date, and `period.preset` echoes it. The result carries totals, by_source and by_page aggregated from all returned data (not only the limit rows); totals.complete=false means the 200-row source cap may have cut data. mode='gaps' is STOPPED and returns only its stopped notice. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. Scope is clicked citations only. This tool has an attached view. When the host shows it, the figures are already on screen: do not repeat them as a table or list in your reply; give only a short takeaway (2-3 sentences).
- 2026-10-11 `get_keyword_performance` changed (description)
  - before: Return Google Search Console query metrics. Pass start_date and end_date together (inclusive JST GSC dates); comparison is the immediately preceding equal-length range. Omitting both uses a rolling now-minus-30-days window. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) for the same periods as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site time zone), and the comparison is the same number of days directly before it; year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date or end_date, and `period.preset` echoes it. Each current and previous window uses a separate dashboard_keywords RPC call, capped at 200 queries by clicks. `period` and `previous_period` show the actual JST date ranges; `date_basis` / `timezone` identify the GSC calendar. `source_windows` exposes the exact p_from/p_to timestamps used for both RPC calls, whether the GSC date bounds are inclusive, and any JST date shared by the two windows. The rolling default has one shared boundary date; explicit date ranges have none. band='all' returns up to limit rows (default 100) with clicks, impressions, CTR, average position, top page and estimated revenue (search-organic RPS × Google clicks); query-matched changes and `truncated` disclose omitted/source-limited rows. A query absent from the previous top 200 may appear new. Explicit dates include both JST GSC dates, while session RPS uses [start, end) and excludes the final microsecond. band='striking' (default limit 10) ranks only candidates among the current top 200, with the search screen's borders (shown rank, the average position rounded to a whole number, from 4 to 20, and at least 10 impressions); it is not the best opportunity across all queries. band='keeping' (default limit 10) returns the search screen's 上位維持 list (shown rank 1 to 3 and at least 10 impressions, most impressions first) and band='declining' (default limit 10) returns its 流入減 list (clicks fell by at least max(3, 20% of the earlier clicks), biggest loss first); both judge only within the current and previous top 200 queries by clicks, and each row has current and previous clicks, impressions and rank (shown_position is the whole-number rank the screen shows), `rise` (previous shown rank minus current, positive is up) and, for declining, click_loss and click_change_pct. Revenue values (est_revenue_jpy, rps_search_jpy, est_revenue_change, est_incremental_revenue_jpy) are null when revenue_status is 'unconfirmed': null means unverified, not 0 yen. Values may differ from the former keyword_breakdown_aggregate because date boundaries, source limit and returned query set differ. Google-search only; data lags 1-2 days. site_id is optional when OAuth-authenticated.
  - after: Return Google Search Console query metrics. Pass start_date and end_date together (inclusive JST GSC dates); comparison is the immediately preceding equal-length range. Omitting both uses a rolling now-minus-30-days window. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) for the same periods as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site time zone), and the comparison is the same number of days directly before it; year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date or end_date, and `period.preset` echoes it. Each current and previous window uses a separate dashboard_keywords RPC call, capped at 200 queries by clicks. `period` and `previous_period` show the actual JST date ranges; `date_basis` / `timezone` identify the GSC calendar. `source_windows` exposes the exact p_from/p_to timestamps used for both RPC calls, whether the GSC date bounds are inclusive, and any JST date shared by the two windows. The rolling default has one shared boundary date; explicit date ranges have none. band='all' returns up to limit rows (default 100) with clicks, impressions, CTR, average position, top page and estimated revenue (search-organic RPS × Google clicks); query-matched changes and `truncated` disclose omitted/source-limited rows. A query absent from the previous top 200 may appear new. Explicit dates include both JST GSC dates, while session RPS uses [start, end) and excludes the final microsecond. band='striking' (default limit 10) ranks only candidates among the current top 200, with the search screen's borders (shown rank, the average position rounded to a whole number, from 4 to 20, and at least 10 impressions); it is not the best opportunity across all queries. band='keeping' (default limit 10) returns the search screen's 上位維持 list (shown rank 1 to 3 and at least 10 impressions, most impressions first) and band='declining' (default limit 10) returns its 流入減 list (clicks fell by at least max(3, 20% of the earlier clicks), biggest loss first); both judge only within the current and previous top 200 queries by clicks, and each row has current and previous clicks, impressions and rank (shown_position is the whole-number rank the screen shows), `rise` (previous shown rank minus current, positive is up) and, for declining, click_loss and click_change_pct. Revenue values (est_revenue_jpy, rps_search_jpy, est_revenue_change, est_incremental_revenue_jpy) are null when revenue_status is 'unconfirmed': null means unverified, not 0 yen. Values may differ from the former keyword_breakdown_aggregate because date boundaries, source limit and returned query set differ. Google-search only; data lags 1-2 days. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id.
- 2026-10-11 `get_breakdown` changed (description, outputSchema)
  - before: `get_breakdown` compares channel, entry_page, visitor_history, page and session_attribute rows. By default it uses the site's calendar month to date and compares with the prior month through the same calendar day (clamped to the prior month's last day). Pass start_date and end_date together for another inclusive calendar range in the site's analysis timezone; optionally pass compare_start_date and compare_end_date. Without explicit comparison dates it uses the immediately preceding equal-length range. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) instead of dates, for the same periods and comparison as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site timezone), the comparison is the same number of days directly before it, and year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date, end_date, compare_start_date or compare_end_date, and `period.preset` echoes it. Each row reports available prior values and deltas. Channel attribution_model supports last_touch, first_touch, linear and time_decay. Candidate ad revenue is not paid attribution. ad_spend_candidates returns ROAS (candidate revenue / ad spend) only for ad-only platforms (Google Ads, Yahoo! Ads, Microsoft Ads, Criteo, RTB House, MicroAd); others such as Meta include organic traffic and get roas_status=includes_organic. Monthly ad spend is prorated by overlapping days. No overall ROAS. Unattributed is the total of purchases that no session carries, shown as a separate row and not added to channel revenue. A purchase after a device change or cookie clearing belongs to the channel of the session it was made in (often Direct) and cannot be separated. revenue_breakdown.total_event_jpy is channel-attributed revenue plus Unattributed, not a total cut by purchase-event time. Some dimensions do not support country/device filters; unsupported axes are identified in notes. site_id is optional when OAuth-authenticated.
  - after: `get_breakdown` compares channel, entry_page, visitor_history, page and session_attribute rows. By default it uses the site's calendar month to date and compares with the prior month through the same calendar day (clamped to the prior month's last day). Pass start_date and end_date together for another inclusive calendar range in the site's analysis timezone; optionally pass compare_start_date and compare_end_date. Without explicit comparison dates it uses the immediately preceding equal-length range. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) instead of dates, for the same periods and comparison as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site timezone), the comparison is the same number of days directly before it, and year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date, end_date, compare_start_date or compare_end_date, and `period.preset` echoes it. Each row reports available prior values and deltas. Channel attribution_model supports last_touch, first_touch, linear and time_decay. Candidate ad revenue is not paid attribution. ad_spend_candidates returns ROAS (candidate revenue / ad spend) only for ad-only platforms (Google Ads, Yahoo! Ads, Microsoft Ads, Criteo, RTB House, MicroAd); others such as Meta include organic traffic and get roas_status=includes_organic. Monthly ad spend is prorated by overlapping days. No overall ROAS. Unattributed is the total of purchases that no session carries, shown as a separate row and not added to channel revenue. A purchase by someone who first came from an ad or a search and later opened the site directly belongs to the channel of the session it was made in (often Direct), so Direct is not only direct visits. When that return is on another device or after cookies were cleared, it cannot be linked to the earlier visit and cannot be separated. revenue_breakdown.total_event_jpy is channel-attributed revenue plus Unattributed, not a total cut by purchase-event time. Some dimensions do not support country/device filters; unsupported axes are identified in notes. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. This tool has an attached view. When the host shows it, the figures are already on screen: do not repeat them as a table or list in your reply; give only a short takeaway (2-3 sentences).
- 2026-10-11 `get_today` changed (description, outputSchema)
  - before: Return today's activity for a site: the site's timezone from 00:00 to now, provisional values. No screen of the RevenueScope app shows this view now. Purchase events are observed events, not confirmed orders; unverified revenue and unavailable sections are not zero. Sample-site values are those of a sample store, not your own site. No event-level or visitor-level rows are returned. For comparison with yesterday at the same time, use get_summary with start_date and end_date both set to today's site-local date. site_id is optional when OAuth-authenticated.
  - after: Return today's activity for a site: the site's timezone from 00:00 to now, provisional values. No screen of the RevenueScope app shows this view now. Purchase events are observed events, not confirmed orders; unverified revenue and unavailable sections are not zero. Sample-site values are those of a sample store, not your own site. No event-level or visitor-level rows are returned. For comparison with yesterday at the same time, use get_summary with start_date and end_date both set to today's site-local date. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. This tool has an attached view. When the host shows it, the figures are already on screen: do not repeat them as a table or list in your reply; give only a short takeaway (2-3 sentences).
- 2026-10-11 `get_summary` changed (description, outputSchema)
  - before: Return headline KPIs (revenue, orders, sessions, RPS, AOV, CVR), engagement metrics and daily trends for the site's calendar month to date, compared with the prior month through the same calendar day (clamped to that month's last day). Pass start_date and end_date together for another inclusive calendar range in the site's analysis timezone; optionally pass compare_start_date and compare_end_date. If comparison dates are omitted, the preceding equal-length range is used. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) instead of dates, for the same periods and comparison as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site timezone), the comparison is the same number of days directly before it, and year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date, end_date, compare_start_date or compare_end_date, and `period.preset` echoes it. Revenue-dependent metrics (revenue, orders, RPS, AOV, CVR) are null unless purchase measurement is confirmed; null means unverified, not zero. Required retrieval failures return isError=true and must not be read as zero. No overall ROAS is returned (kpis.roas is always null); per-platform ROAS for ad-only platforms is in get_breakdown ad_spend_candidates. Optional country (ISO2) and device filters scope session-derived metrics. site_id is optional when OAuth-authenticated.
  - after: Return headline KPIs (revenue, orders, sessions, RPS, AOV, CVR), engagement metrics and daily trends for the site's calendar month to date, compared with the prior month through the same calendar day (clamped to that month's last day). Pass start_date and end_date together for another inclusive calendar range in the site's analysis timezone; optionally pass compare_start_date and compare_end_date. If comparison dates are omitted, the preceding equal-length range is used. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) instead of dates, for the same periods and comparison as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site timezone), the comparison is the same number of days directly before it, and year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date, end_date, compare_start_date or compare_end_date, and `period.preset` echoes it. Revenue-dependent metrics (revenue, orders, RPS, AOV, CVR) are null unless purchase measurement is confirmed; null means unverified, not zero. Required retrieval failures return isError=true and must not be read as zero. No overall ROAS is returned (kpis.roas is always null); per-platform ROAS for ad-only platforms is in get_breakdown ad_spend_candidates. Optional country (ISO2) and device filters scope session-derived metrics. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. This tool has an attached view. When the host shows it, the figures are already on screen: do not repeat them as a table or list in your reply; give only a short takeaway (2-3 sentences).
- 2026-10-11 `get_competitor_keywords` changed (title, description, inputSchema, outputSchema, annotations) **meaning changed**
  - before: Return the latest competitor SEO snapshot for the site which keywords each tracked competitor DOMAIN ranks for on Google (Japan/ja), at what position, with monthly search_volume, cpc and etv (estimated monthly traffic — a visit estimate, not a monetary value), plus how each rank moved vs the previous snapshot. READ-ONLY — this tool never runs a research (that costs money and is triggered separately from the RevenueScope app by the competitor-research Edge Function); it only reads what was already fetched. The response is summary-first (token-aware): each domain carries a constant-size `summary` (total_keywords, total_etv, volume_bands and rank_bands histograms, and vs_previous new/lost/improved/declined/same counts) that always reflects the FULL keyword set, while `keywords` returns only the top rows ranked by `sort` (etv default | volume | rank; default limit 10 per domain, max 100) with a `truncated` block (shown/matching_total/lost_total). rank is a POSITION: smaller is better, so a NEGATIVE rank_delta means the competitor's ranking IMPROVED (change ∈ new/improved/declined/same/unknown). Keywords the competitor ranked for before but lost are disclosed in `lost_keywords` (top 10 by previous etv), never dropped silently. Pass `domain` to focus one competitor, `min_volume` to drop low-volume keywords. When the site has NO completed research yet the response is { researched:false } with a `guidance` string explaining a research must be triggered from the RevenueScope app first — this tool cannot start one. site_id is OPTIONAL when OAuth-authenticated. This is the external competitor lens (third-party SERP data); for YOUR OWN search performance use get_keyword_performance, and for your content playbook use get_content_actions.
  - after: Return the keywords where the site's PEER SHOPS (up to 3 shops of a similar size that compete for the same searches) rank in Google's top 10 (Japan/ja), each listed beside the site's OWN rank, from the latest completed research of third-party search-result data. READ-ONLY — this tool never starts a research (a research is started from the search screen of the RevenueScope app and uses a monthly allowance); it only reads what was already fetched. The values equal the app's search screen ("Rank breakdown"); nothing is recounted. `counts` (total/top/near/out/unknown) always cover ALL keywords, independent of `band` and `limit`. `keywords` returns `limit` keywords (default 10, max 100) ordered by monthly search_volume (high first), starting at `offset`; `truncated` ({shown, matching_total, next_offset}) says whether more remain (a large limit can exceed the default output budget; page with offset instead). `band` filters by the site's own rank: top = 1-3, near = 4-20, out = 21 or lower or not in the top 100, unknown = the own rank could not be fetched (unknown is NOT out). Each keyword has own_rank / own_status (ranked | not_in_top100 | unknown) / own_url, top_domain and top_rank (the best peer), and every peer's rank in `peers`. `shops` lists the peer shops (scale_ratio is an estimated ratio of search traffic, not of revenue or visits; fetch_failed marks a shop whose fetch failed). Ranks are organic-result positions 1-100 and are NOT comparable with the ranks this tool returned before v7. No rank change, ETV or CPC is returned, and no previous research is compared. When the site has NO completed research of this kind the response is { researched:false } with a `guidance` string. site_id is OPTIONAL when OAuth-authenticated. For YOUR OWN search performance use get_keyword_performance, and for your content playbook use get_content_actions.
- 2026-10-10 `suggest_budget_allocation` removed
  - STOPPED. This tool no longer returns a budget split: the old method weighted every channel by revenue ÷ ad spend, which RevenueScope no longer provides (it returns ROAS for ad-only platforms only). It always returns status='stopped' with the reason, the alternative (get_breakdown lists each channel's ad spend next to candidate paid-session revenue, with ROAS for ad-only platforms only) and the resume plan (a new method after paid-traffic classification). Do not present anything from this tool as a recommendation.
- 2026-10-10 `get_priority_insights` removed
  - STOPPED. This tool no longer returns insights: its old rules (ROAS, saturation) do not match the current RevenueScope definitions. It always returns status='stopped' with the reason and the tools to use instead (get_summary for period KPIs, get_breakdown for channel / entry-page / visitor-history changes). Do not present anything from this tool as a recommendation.

Full history: https://api.protogrid.dev/v1/servers/io.github.toshihiroshishido%2Frevenuescope-mcp/changes

## Remotes

- https://mcp.revenuescope.jp/api/mcp (streamable-http, auth none, reachable false, uptime30d 0.94736844)

## Packages

_none_

## Tools (10)

- `get_ai_traffic`: Return AI-assistant traffic using dashboard_ai_referred, a separate RPC from the AI channels of dashboard_channels that the search screen shows (for the screen's number, use the AI channel in get_breakdown(dimension='channel')). By default, mode='referred' uses the site's calendar month to date and compares with the prior month through the same calendar day (clamped to the prior month's last day). Pass start_date and end_date together for another inclusive calendar range in the site's analysis timezone; optionally pass compare_start_date and compare_end_date. If comparison dates are omitted, the immediately preceding equal-length range is used. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) instead of dates, for the same periods and comparison as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site timezone), the comparison is the same number of days directly before it, and year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date, end_date, compare_start_date or compare_end_date, and `period.preset` echoes it. The result carries totals, by_source and by_page aggregated from all returned data (not only the limit rows); totals.complete=false means the 200-row source cap may have cut data. mode='gaps' is STOPPED and returns only its stopped notice. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. Scope is clicked citations only. This tool has an attached view. When the host shows it, the figures are already on screen: do not repeat them as a table or list in your reply; give only a short takeaway (2-3 sentences).
- `get_breakdown`: `get_breakdown` compares channel, entry_page, visitor_history, page and session_attribute rows. By default it uses the site's calendar month to date and compares with the prior month through the same calendar day (clamped to the prior month's last day). Pass start_date and end_date together for another inclusive calendar range in the site's analysis timezone; optionally pass compare_start_date and compare_end_date. Without explicit comparison dates it uses the immediately preceding equal-length range. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) instead of dates, for the same periods and comparison as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site timezone), the comparison is the same number of days directly before it, and year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date, end_date, compare_start_date or compare_end_date, and `period.preset` echoes it. Each row reports available prior values and deltas. Channel attribution_model supports last_touch, first_touch, linear and time_decay. Candidate ad revenue is not paid attribution. ad_spend_candidates returns ROAS (candidate revenue / ad spend) only for ad-only platforms (Google Ads, Yahoo! Ads, Microsoft Ads, Criteo, RTB House, MicroAd); others such as Meta include organic traffic and get roas_status=includes_organic. Monthly ad spend is prorated by overlapping days. No overall ROAS. Unattributed is the total of purchases that no session carries, shown as a separate row and not added to channel revenue. A purchase by someone who first came from an ad or a search and later opened the site directly belongs to the channel of the session it was made in (often Direct), so Direct is not only direct visits. When that return is on another device or after cookies were cleared, it cannot be linked to the earlier visit and cannot be separated. revenue_breakdown.total_event_jpy is channel-attributed revenue plus Unattributed, not a total cut by purchase-event time. Some dimensions do not support country/device filters; unsupported axes are identified in notes. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. This tool has an attached view. When the host shows it, the figures are already on screen: do not repeat them as a table or list in your reply; give only a short takeaway (2-3 sentences).
- `get_competitor_keywords`: Return the keywords where the site's PEER SHOPS (up to 3 shops of a similar size that compete for the same searches) rank in Google's top 10 (Japan/ja), each listed beside the site's OWN rank, from the latest completed research of third-party search-result data. READ-ONLY — this tool never starts a research (a research is started from the search screen of the RevenueScope app and uses a monthly allowance); it only reads what was already fetched. The values equal the app's search screen ("Rank breakdown"); nothing is recounted. `counts` (total/top/near/out/unknown) always cover ALL keywords, independent of `band` and `limit`. `keywords` returns `limit` keywords (default 10, max 100) ordered by monthly search_volume (high first), starting at `offset`; `truncated` ({shown, matching_total, next_offset}) says whether more remain (a large limit can exceed the default output budget; page with offset instead). `band` filters by the site's own rank: top = 1-3, near = 4-20, out = 21 or lower or not in the top 100, unknown = the own rank could not be fetched (unknown is NOT out). Each keyword has own_rank / own_status (ranked | not_in_top100 | unknown) / own_url, top_domain and top_rank (the best peer), and every peer's rank in `peers`. `shops` lists the peer shops (scale_ratio is an estimated ratio of search traffic, not of revenue or visits; fetch_failed marks a shop whose fetch failed). Ranks are organic-result positions 1-100 and are NOT comparable with the ranks this tool returned before v7. No rank change, ETV or CPC is returned, and no previous research is compared. When the site has NO completed research of this kind the response is { researched:false } with a `guidance` string. site_id is OPTIONAL when OAuth-authenticated. For YOUR OWN search performance use get_keyword_performance, and for your content playbook use get_content_actions.
- `get_content_actions`: Return content action buckets and page evidence. By default the window length is N=7 days and GSC data is delayed by 3 days. To choose a window, pass start_date and end_date together: end_date must be today's date in Japan time, and N is end_date minus start_date (2-365 days; e.g. September 21 through September 28 sets N=7), so the pair describes a length ending today rather than the GSC source dates. The response separates `window` (actual JST GSC dates, inclusive) from `session_window` (sessions, revenue and AI metrics over N×24 hours ending at database statement time). `session_window` gives the relative start/end and duration; exact timestamps are unavailable because the RPC does not return its `now()` value. Search classifications, thresholds, bucket_summary, row prioritization, caveats and limits are included in the response. A page carries `title_change` when its title was rewritten within the last 8 weeks (detected from the titles the tracker recorded): do not recommend another title rewrite for it while it is tracked, and read a rank change since the rewrite as a before/after comparison, not proof of effect. The app's home screen takes such pages off its to-do list, but this tool keeps them and their order in `pages` and only adds the mark; `title_changes.status` is 'unavailable' when the marks could not be read. Revenue values (revenue_jpy, ai_revenue_jpy, expected_revenue_gain and the bucket_summary revenue_jpy) are null when revenue_status is 'unconfirmed': null means unverified, not 0 yen. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. Google Search only; data lags 1-2 days.
- `get_keyword_performance`: Return Google Search Console query metrics. Pass start_date and end_date together (inclusive JST GSC dates); comparison is the immediately preceding equal-length range. Omitting both uses a rolling now-minus-30-days window. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) for the same periods as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site time zone), and the comparison is the same number of days directly before it; year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date or end_date, and `period.preset` echoes it. Each current and previous window uses a separate dashboard_keywords RPC call, capped at 200 queries by clicks. `period` and `previous_period` show the actual JST date ranges; `date_basis` / `timezone` identify the GSC calendar. `source_windows` exposes the exact p_from/p_to timestamps used for both RPC calls, whether the GSC date bounds are inclusive, and any JST date shared by the two windows. The rolling default has one shared boundary date; explicit date ranges have none. band='all' returns up to limit rows (default 100) with clicks, impressions, CTR, average position, top page and estimated revenue (search-organic RPS × Google clicks); query-matched changes and `truncated` disclose omitted/source-limited rows. A query absent from the previous top 200 may appear new. Explicit dates include both JST GSC dates, while session RPS uses [start, end) and excludes the final microsecond. band='striking' (default limit 10) ranks only candidates among the current top 200, with the search screen's borders (shown rank, the average position rounded to a whole number, from 4 to 20, and at least 10 impressions); it is not the best opportunity across all queries. band='keeping' (default limit 10) returns the search screen's 上位維持 list (shown rank 1 to 3 and at least 10 impressions, most impressions first) and band='declining' (default limit 10) returns its 流入減 list (clicks fell by at least max(3, 20% of the earlier clicks), biggest loss first); both judge only within the current and previous top 200 queries by clicks, and each row has current and previous clicks, impressions and rank (shown_position is the whole-number rank the screen shows), `rise` (previous shown rank minus current, positive is up) and, for declining, click_loss and click_change_pct. Revenue values (est_revenue_jpy, rps_search_jpy, est_revenue_change, est_incremental_revenue_jpy) are null when revenue_status is 'unconfirmed': null means unverified, not 0 yen. Values may differ from the former keyword_breakdown_aggregate because date boundaries, source limit and returned query set differ. Google-search only; data lags 1-2 days. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id.
- `get_metadata`: Return RevenueScope metric definitions, measurement boundaries, and the meaning of confirmed, unconfirmed, zero, sample, comparison-unavailable and retrieval-error states. This is generic metadata; use a site-scoped analytics tool for values. A missing purchase history does not prove purchase tracking is unconfigured.
- `get_page_trend`: Return how ONE page's Google Search performance changed over time. Pass start_date and end_date together as inclusive JST dates; comparison dates are not supported. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) for the same periods as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site time zone), and year_to_date starts on January 1 of the year of that Saturday; preset cannot be combined with start_date or end_date, and `period.preset` echoes it. Omitting all of them preserves the current now-minus-30-days rolling window, which may touch 31 JST dates because GSC filters by date inclusively. Explicit dates are converted to JST day boundaries for GSC rows. `granularity` defaults to day for windows up to about 35 days and week for longer windows; pass it to override. Weeks run Sunday to Saturday and each weekly `date` is that week's Sunday; weeks at the edge of the period hold only the days inside it. Buckets without GSC rows are omitted. Google-search only; data lags 1-2 days. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. For cross-page snapshots use get_breakdown(dimension='page'); for query trends use get_keyword_performance.
- `get_summary`: Return headline KPIs (revenue, orders, sessions, RPS, AOV, CVR), engagement metrics and daily trends for the site's calendar month to date, compared with the prior month through the same calendar day (clamped to that month's last day). Pass start_date and end_date together for another inclusive calendar range in the site's analysis timezone; optionally pass compare_start_date and compare_end_date. If comparison dates are omitted, the preceding equal-length range is used. Or pass preset (last_4_weeks, last_12_weeks or year_to_date) instead of dates, for the same periods and comparison as the app's period picker: the period ends on the last Saturday that closes a complete week (weeks run Sunday to Saturday, judged in the site timezone), the comparison is the same number of days directly before it, and year_to_date starts on January 1 of the year of that Saturday. preset cannot be combined with start_date, end_date, compare_start_date or compare_end_date, and `period.preset` echoes it. Revenue-dependent metrics (revenue, orders, RPS, AOV, CVR) are null unless purchase measurement is confirmed; null means unverified, not zero. Required retrieval failures return isError=true and must not be read as zero. No overall ROAS is returned (kpis.roas is always null); per-platform ROAS for ad-only platforms is in get_breakdown ad_spend_candidates. Optional country (ISO2) and device filters scope session-derived metrics. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. This tool has an attached view. When the host shows it, the figures are already on screen: do not repeat them as a table or list in your reply; give only a short takeaway (2-3 sentences).
- `get_today`: Return today's activity for a site: the site's timezone from 00:00 to now, provisional values. No screen of the RevenueScope app shows this view now. Purchase events are observed events, not confirmed orders; unverified revenue and unavailable sections are not zero. Sample-site values are those of a sample store, not your own site. No event-level or visitor-level rows are returned. For comparison with yesterday at the same time, use get_summary with start_date and end_date both set to today's site-local date. site_id is optional when OAuth-authenticated (omitting it uses the primary site). When the user names a specific site, such as the sample site, call list_sites first and pass that site_id. This tool has an attached view. When the host shows it, the figures are already on screen: do not repeat them as a table or list in your reply; give only a short takeaway (2-3 sentences).
- `list_sites`: List the sites this signed-in account can analyze, in two groups. Each site includes its timezone and today's date in that timezone. Requires OAuth; no site registration is needed. Prefer my_sites; if site_id is omitted, analytics tools use the primary site. When my_sites is empty, analytics tools use the first curated demo site and identify it as sample data.
