Awesome MCP Servers by AI Anytime

Directory / Cloud, ops & data

ExtensionDash

Hosted MCP access to Chrome and Firefox extension user counts, ratings and search-rank monitoring. OAuth required. Endpoint: https://extensiondash.com/mcp · Website

Live  Answered an MCP handshake without credentials and listed 14 tools.

Category
Cloud, ops & data
Transport
http
Source
https://extensiondash.com/
Endpoint
https://extensiondash.com/mcp
MCP Registry
io.github.tonic20/extensions-dashboard
Reports itself as
extensions-dashboard 1.0.0
Protocol
2025-06-18
Tools
14
Context cost
about 5,430 tokens for the tool definitions (estimated at four characters per token)
Tool definitions last changed
no change seen since first check
Handshake time
139 ms
Last checked
2026-11-03 10:54:39 UTC
Listed since
2026-10-25

Health and compatibility

Endpoint reachableVerifiedResponded in 139 ms
MCP handshake (initialize)VerifiedCompleted without credentials
Tool discovery (tools/list)Verified14 tools listed
AuthenticationVerifiedNone needed to connect
Protocol versionVerified2025-06-18
TransportVerifiedStreamable HTTP
Capabilities declaredVerifiedtools

Last checked . Verified means the check saw it happen; it says nothing about whether the server is safe.

Recent history

5 daily checks so far; median response 139 ms. Green answered, violet asked for auth, red did not answer.

Set up in your client

Claude Code

Run this in a terminal:

claude mcp add --transport http extensiondash https://extensiondash.com/mcp

Claude Desktop

Open Settings → Connectors → Add custom connector and paste this URL:

https://extensiondash.com/mcp

Or bridge it through mcp-remote in claude_desktop_config.json (needs Node.js):

{
  "mcpServers": {
    "extensiondash": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://extensiondash.com/mcp"
      ]
    }
  }
}

Cursor

Add to Cursor

Or add it to ~/.cursor/mcp.json (or .cursor/mcp.json in a project):

{
  "mcpServers": {
    "extensiondash": {
      "url": "https://extensiondash.com/mcp"
    }
  }
}

VS Code

Add to VS Code

Or add it to .vscode/mcp.json:

{
  "servers": {
    "extensiondash": {
      "type": "http",
      "url": "https://extensiondash.com/mcp"
    }
  }
}

Or from a terminal:

code --add-mcp '{"name": "extensiondash", "type": "http", "url": "https://extensiondash.com/mcp"}'

Windsurf

Add it to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "extensiondash": {
      "serverUrl": "https://extensiondash.com/mcp"
    }
  }
}

Other clients

Most clients accept this shape. The endpoint is:

https://extensiondash.com/mcp
{
  "mcpServers": {
    "extensiondash": {
      "type": "http",
      "url": "https://extensiondash.com/mcp"
    }
  }
}

If it does not connect

Tools 14

Names, descriptions and input schemas exactly as the server returned them on 2026-11-03. This is the server author's own text. Nothing is run from this page. Labels such as read-only are declared by the server and are not verified. Raw JSON

add_competitorcan modifydestructiveexternal accessStart tracking a competitor for an extension. Takes the store and id of a search_catalog row (as …

Start tracking a competitor for an extension. Takes the store and id of a search_catalog row (as external_id), so a listing you just found can be promoted without looking anything up in between. Promoting a listing is what earns it a store fetch: its description, install count, rating and languages start being recorded, and its position is kept even on days it falls out of the results entirely. Where it ranks has been recorded all along, from the searches this account already runs — so a competitor added today arrives with history rather than starting from zero. The description is not available when this returns. Call list_competitors with the same extension_id until this competitor's status turns from "pending" to "scraped". At most 5 competitors per store on the Free plan and 20 on Premium, because each costs a fetch of that store on every refresh. The two stores are counted separately. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

ParameterTypeDescription
extension_idintegerrequiredFrom list_extensions.
storestringrequiredOne of: chrome, firefox
external_idstringrequiredChrome's 32-letter id or the AMO slug, as a search_catalog row's id gives it.

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "add_competitor",
    "arguments": {
      "extension_id": 0,
      "store": "chrome",
      "external_id": "..."
    }
  }
}
add_keywordcan modifydestructiveexternal accessStart tracking a search term for an extension. The term is added once per store the extension is listed in, …

Start tracking a search term for an extension. The term is added once per store the extension is listed in, and a rank fetch is enqueued for each store that was not already tracking it. The position is not available when this returns. Call list_keywords with the same extension_id until this term's status turns from "pending" to "scanned", or list_scrape_runs to watch the fetch itself — a fetch that fails shows up there, rather than as a position that never arrives. A term is tracked per store language. Tracking "ad blocker" in en and again in de gives two independent keywords with their own positions. Call list_keywords for the languages an extension already tracks. An extension tracks at most 10 keywords on the Free plan and 50 on Premium, counted per language: "ad blocker" in en and de is two. Past that this returns a limit error and remove_keyword has to free a slot first. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

ParameterTypeDescription
extension_idintegerrequiredFrom list_extensions.
termstringrequiredThe search term, e.g. "json viewer". Squished and lowercased before use.
localestringoptionalStore language to search in: "en", "de", "pt-BR". Defaults to "en". The same term ranks differently in each, so this is a separate keyword, not a translation. Canonicalised before use, so "DE" and "de" are one keyword and "pt-br" comes back as "pt-BR".

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "add_keyword",
    "arguments": {
      "extension_id": 0,
      "term": "..."
    }
  }
}
get_extensionread-onlyOne extension in full: every store listing's latest numbers plus its tracked keywords and their current …

One extension in full: every store listing's latest numbers plus its tracked keywords and their current positions. Each listing's rank is its position by users within its store, computed from the current user count; ties share a rank (rank_tied = others at the same count); rank_change is the move since last week's recorded rank. locales lists every store language this extension tracks, with a keyword count each, so the keywords can be worked a language at a time. Use get_metrics_history or get_keyword_ranks for movement over time. This is the tracked view, built from what we have recorded. For an extension this account does not track, use get_listing instead. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

ParameterTypeDescription
extension_idintegerrequiredFrom list_extensions.

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "get_extension",
    "arguments": {
      "extension_id": 0
    }
  }
}
get_keyword_ranksread-onlyDaily search position history for an extension's tracked keywords, one series per term per store. Every point …

Daily search position history for an extension's tracked keywords, one series per term per store. Every point carries the depth it was scanned to, because a position only means something against the size of the pool it came from: #1 of 9 and #1 of 50 are different results. A null position means we searched that deep and this extension was not in the results. A term tracked in more than one store language comes back as one series per language — the same term is a different SERP in each. Each series has a source. "store" is the store's own search. "google" is where the listing page ranks in Google: organic results only (ads and other blocks are not counted), top 50, desktop, in the keyword language's country (English: the United States). A null Google position means Google was searched 50 deep and the listing was not there. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

ParameterTypeDescription
extension_idintegerrequiredFrom list_extensions.
termstringoptionalOne term. Omit for all of them.
storestringoptionalOne of: chrome, firefox
localestringoptionalStore language, e.g. "de". Omit for every language. Canonicalised before use, so "DE" and "de" are one keyword and "pt-br" comes back as "pt-BR".
sourcestringoptionalStore search or Google. Omit for both. One of: store, google
daysintegeroptionalHow far back to look. Defaults to 30.

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "get_keyword_ranks",
    "arguments": {
      "extension_id": 0
    }
  }
}
get_keyword_serpread-onlyThe search page for one of an extension's tracked keywords, as this account last recorded it — who was on it, …

The search page for one of an extension's tracked keywords, as this account last recorded it — who was on it, in what order, and which way each of them moved over the past week. Read from recorded history, not from the store: no fetch, no waiting, no egress spent. Use this when you want movement, or the same page the dashboard is showing. Every row carries mine and competitor flags, so "who is above me and which of them am I already tracking" is one call. Positions always travel with depth_scanned, because #1 of 9 and #1 of 50 are different results. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

ParameterTypeDescription
extension_idintegerrequiredFrom list_extensions.
storestringrequiredOne of: chrome, firefox
termstringrequiredA term this extension tracks. From list_keywords.
localestringoptionalStore language. Defaults to "en".
windowbooleanoptionalReturn only the leaders and our own neighbourhood rather than the whole page. Defaults to false.

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "get_keyword_serp",
    "arguments": {
      "extension_id": 0,
      "store": "chrome",
      "term": "..."
    }
  }
}
get_listingread-onlyexternal accessOne extension's full listing from the catalog -- any extension, tracked by this account or not: description, …

One extension's full listing from the catalog -- any extension, tracked by this account or not: description, users, rating, reviews, version, languages, categories, permissions and publisher. Pass the store and id of a search_catalog row as store and external_id. rank is the position by users within the store; ties share a rank (rank_tied = others at the same count); recomputed weekly on rank_on; rank_change is the move since the week before, positive = up. English copy, refreshed weekly from the store; refreshed_at says when. This never fetches, never answers "pending" and never starts tracking. users, rating and reviews are null when the store shows no number, which is not zero. For an extension this account tracks, get_metrics_history has its numbers over time. Shares search_catalog's 60 calls a minute per account. Works without an account too.

ParameterTypeDescription
storestringrequiredOne of: chrome, firefox
external_idstringrequiredChrome's 32-letter id or the AMO slug, as a search_catalog row's id gives it.

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "get_listing",
    "arguments": {
      "store": "chrome",
      "external_id": "..."
    }
  }
}
get_metrics_historyread-onlyDaily-or-sparser history of an extension's numbers: user count, rating and ratings count, each as a map of …

Daily-or-sparser history of an extension's numbers: user count, rating and ratings count, each as a map of ISO date to value. "listings" is this extension's own store listings; "competitors" is its roster from list_competitors. store and days filter both. A map holds only dates actually observed; an empty map means no measurement in range, never zero. If users_rounded_in_range is true the store published rounded counts somewhere in the window, so small movements there may be rounding. Competitors are captured every few days rather than daily, and not on a fixed schedule, so compare a rival against "listings" on dates present in both, never by position in the map. Join a competitor entry back to list_competitors on (store, external_id); name is a label, not an identifier. include_competitors adds every roster competitor's history. competitors narrows that to specific (store, external_id) pairs and implies include_competitors; a pair not on the roster fails the whole call rather than silently dropping it. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

ParameterTypeDescription
extension_idintegerrequiredFrom list_extensions.
storestringoptionalFilters both listings and competitors. Omit for every store. One of: chrome, firefox
daysintegeroptionalHow far back to look. Defaults to 30.
include_competitorsbooleanoptionalAlso return history for this extension's promoted competitors. Defaults to false.
competitorsobject[]optionalLimit competitor history to these (store, external_id) pairs from list_competitors. Implies include_competitors; an unlisted pair fails the call.

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "get_metrics_history",
    "arguments": {
      "extension_id": 0
    }
  }
}
list_competitorsread-onlyWho this extension competes with, measured across every keyword it tracks. Two sets. "competitors" is the …

Who this extension competes with, measured across every keyword it tracks. Two sets. "competitors" is the roster you promoted with add_competitor: their descriptions, install counts and ratings are recorded, and their positions are kept even on days they fall out of the results. "candidates" — returned only with include_observed — is everyone else who has appeared in those searches, ranked by how often they beat you. Both are read from positions this account already recorded, not from the store: no fetch, no waiting, and each row carries the evidence behind it (how many of your terms, average position, first seen). This is the tool for deciding who is worth promoting. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

ParameterTypeDescription
extension_idintegerrequiredFrom list_extensions.
include_observedbooleanoptionalAlso return unpromoted candidates. Defaults to false.

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "list_competitors",
    "arguments": {
      "extension_id": 0
    }
  }
}
list_extensionsread-onlyEvery extension this token's owner tracks, with each store listing's latest numbers: user count (and whether …

Every extension this token's owner tracks, with each store listing's latest numbers: user count (and whether the store rounded it), the 7-day change, rating, ratings count and category rank. Start here when this connection has an account: every tracking tool takes an extension_id from this list. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

Takes no parameters.

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "list_extensions",
    "arguments": {}
  }
}
list_keywordsread-onlyEvery search term tracked for one extension, one row per term per store. status is "pending" until a fetch …

Every search term tracked for one extension, one row per term per store. status is "pending" until a fetch has landed since the term was tracked, and "scanned" once one has. A "scanned" row with a null position means we searched depth_scanned results and this extension was not among them — that is a real observation, not missing data. A "pending" row can still carry a position. Removing a keyword stops the tracking but keeps the history, so a term tracked before and added again arrives with its previous result already in place; captured_on says how old that is. Poll until the status reads "scanned" to know the number answers the current tracking. locale is the store language the term was searched in. The same term ranks differently under hl=de than under hl=en, so two rows sharing a term and a store are two different results. locales lists every store language this extension tracks, with a keyword count each — start there to work a language at a time. It always reports every language, including when the locale argument narrows the rows to one. search_volume is Google Ads' average monthly searches for the term in the row's store language: for English, in the United States or worldwide as the account's profile setting says (United States unless changed), and in one country for the others (Germany for de, Spain for es, Brazil for pt-BR, and so on). It is web search demand, not searches inside the store, and is the same for both stores. null means not fetched yet, Google …

ParameterTypeDescription
extension_idintegerrequiredFrom list_extensions.
localestringoptionalStore language, e.g. "de". Omit for every language. Canonicalised before use, so "DE" and "de" are one keyword and "pt-br" comes back as "pt-BR".

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "list_keywords",
    "arguments": {
      "extension_id": 0
    }
  }
}
list_scrape_runsread-onlyRecent scrape attempts against your own extensions, newest first, with their outcome and any error. Covers …

Recent scrape attempts against your own extensions, newest first, with their outcome and any error. Covers both the listing fetches and the rank fetches for the search terms they track. Use this after add_keyword to watch the rank fetch: the run is targeted at the search term, and a failed fetch appears here as a failure rather than as a position that never arrives. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

ParameterTypeDescription
statusstringoptionalOne of: running, success, failure
extension_idintegeroptionalNarrow to one extension's listings and tracked keywords.
limitintegeroptionalDefaults to 20.

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "list_scrape_runs",
    "arguments": {}
  }
}
remove_competitorcan modifydestructiveStop tracking a competitor for an extension. Stops the store fetches. The recorded history is kept, so adding …

Stop tracking a competitor for an extension. Stops the store fetches. The recorded history is kept, so adding the same competitor again later restores its charts rather than starting from zero — and its positions carry on being observed either way, because they come from searches this account already runs. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

ParameterTypeDescription
extension_idintegerrequiredFrom list_extensions.
storestringrequiredOne of: chrome, firefox
external_idstringrequiredFrom list_competitors.

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "remove_competitor",
    "arguments": {
      "extension_id": 0,
      "store": "chrome",
      "external_id": "..."
    }
  }
}
remove_keywordcan modifydestructiveStop tracking a search term for an extension, across every store it was tracked in. Positions already …

Stop tracking a search term for an extension, across every store it was tracked in. Positions already recorded are kept; only the tracking stops. Other extensions tracking the same term are unaffected, including ones that track the same store listing: every extension's keywords are its own. A term is tracked per store language. Tracking "ad blocker" in en and again in de gives two independent keywords with their own positions. Call list_keywords for the languages an extension already tracks. Needs an ExtensionDash account: sign in from your app, e.g. `claude mcp login extensions-dashboard` or `codex mcp login extensions-dashboard`.

ParameterTypeDescription
extension_idintegerrequiredFrom list_extensions.
termstringrequiredAs reported by list_keywords.
localestringoptionalStore language to search in: "en", "de", "pt-BR". Defaults to "en". The same term ranks differently in each, so this is a separate keyword, not a translation. Canonicalised before use, so "DE" and "de" are one keyword and "pt-br" comes back as "pt-BR".

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "remove_keyword",
    "arguments": {
      "extension_id": 0,
      "term": "..."
    }
  }
}
search_catalogread-onlyexternal accessSearch one store's catalog of extensions fetched so far, for market and niche research: store "chrome" …

Search one store's catalog of extensions fetched so far, for market and niche research: store "chrome" (default) or "firefox", one per call -- Chrome users are a rounded weekly count, Firefox's an exact daily average, so the two are never mixed. listed and known in each answer show how much of that store the catalog covers. rank is the position by users within the store; ties share a rank (rank_tied = others at the same count); recomputed weekly on rank_on; rank_change is the move since the week before, positive = up. Filter by name words (match "all" or "any"; case and punctuation are ignored, and an exact name comes first unless you sort), by one category of that store (a slug such as "productivity/developer" or "privacy-security"; an unknown one is refused with the store's list) and by inclusive ranges on users, rating, reviews, language count and description length; sort by any of those or by last update. This never fetches the store. users, rating and reviews are null when the store shows no number, which is not zero. Each row says whether it is one of yours or a competitor you track; pass its store and id to add_competitor to start tracking it. For one extension's full listing, call get_listing. Allows 60 calls a minute per account. Works without an account too.

ParameterTypeDescription
storestringoptionalDefaults to chrome. One of: chrome, firefox
categorystringoptionalOne category slug of the chosen store, as rows return it.
querystringoptionalName words, at most 8 words.
matchstringoptionalDefaults to all. One of: all, any
sortstringoptionalDefaults to users, with an exact name match first when query is given. One of: users, rating, reviews, langs, description_length, screenshots, updated, added
dirstringoptionalDefaults to desc. Nulls always last. One of: desc, asc
limitintegeroptionalDefaults to 25.
pageintegeroptionalDefaults to 1.
users_minintegeroptional
users_maxintegeroptional
rating_minnumberoptional
rating_maxnumberoptional
reviews_minintegeroptional
reviews_maxintegeroptional
description_length_minintegeroptional
description_length_maxintegeroptional
langs_minintegeroptional
langs_maxintegeroptional
screenshots_minintegeroptional
screenshots_maxintegeroptional

Example call (required arguments only, placeholder values):

{
  "method": "tools/call",
  "params": {
    "name": "search_catalog",
    "arguments": {}
  }
}

Badge

Maintain this server? Put its live status in your README:

MCP status badge

[![MCP status](https://mcp.aianytime.net/badge/extensiondash.svg)](https://mcp.aianytime.net/s/extensiondash/)

Edit this entry · Report a problem

More in Cloud, ops & data

Checks record what a server answered, not whether it is safe. A listing is not a security audit; read a server's source and permissions before you connect it. Add a server · JSON · llms.txt · llms-full.txt

Browse: Agents, IDEs & developer tools · Search & discovery · Knowledge, memory & context · Media & generation · Security · Finance & markets · Marketing, content & social · Cloud, ops & data · Commerce, travel & logistics · Work & productivity · No account needed · Local servers