Back to Directory/Developer Tools

io.github.cyanheads/browser-compat-mcp-server

Browser compatibility and Baseline status for any web feature — offline, from bundled MDN data.

Developer ToolsTypeScriptv0.2.0

@cyanheads/browser-compat-mcp-server

Browser compatibility and Baseline status for any web feature — offline, from MDN's browser-compat-data, web-features, and caniuse. STDIO or Streamable HTTP.

5 Tools

npm License MCP SDK Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework


Overview

Web platform compatibility for frontend work: per-browser support from MDN's @mdn/browser-compat-data, Baseline state and dates from web-features, and browserslist target resolution weighted by caniuse-lite usage figures. Every dataset ships inside the package, so there are no runtime network calls, no API key, no rate limit, and no upstream to be down — the same answers come back air-gapped. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.

Tools

ToolDescription
browsercompat_list_referenceEnumerate the reference vocabulary the other tools expect — BCD namespaces and browser ids, browserslist agents, Baseline states, groups, and ECMAScript snapshots.
browsercompat_get_featureFull compatibility record for one feature: Baseline state, standards status, per-browser versions with flags and prefixes, MDN and specification links.
browsercompat_check_baselineShip-or-not across up to 20 features: Baseline state and date, the limiting browser, deprecation flags, and the traffic share requiring it would exclude.
browsercompat_search_featuresFind features by plain name, keyword, or code notation when the canonical key is unknown, ranked with the field that matched, filterable by group or ECMAScript snapshot, and pageable.
browsercompat_compare_supportCheck features against an explicit browserslist target query, reporting the failing target per feature and every target that could not be evaluated.

Capability reference

browsercompat_list_reference tool

  • One required topic: bcd_namespaces (12), bcd_browsers (17), browserslist_agents (19), baseline_states (4), groups (104), snapshots (11)
  • Entries carry id, label, and detail, plus count, reported, bcd_browser, usage_percent, maps_from, or spec_url where the topic has them
  • groups and snapshots ids are the values browsercompat_search_features takes as group and snapshot
  • browserslist_agents gives each agent's browser-compat-data counterpart or null — the null ones can never be evaluated and always land in unchecked_targets

browsercompat_get_feature tool

  • One feature string, 1–200 characters: a BCD key (css.selectors.has) or a web-features id (has); resolved_as echoes which one matched and how
  • resolve: true falls back to the search index for a plain name or notation (Container queries, Element.prototype.animate) and accepts its best exact matches only when they name one feature: one key resolves to that key, several keys of one feature resolve to the feature with compat_keys, and two features are a miss. Off by default, so a typo returns a miss rather than a confident answer about the wrong feature
  • include_runtimes: true adds bun, deno, nodejs, and oculus rows to the 13 reported desktop and mobile browsers
  • outcome is found | no_compat_data | miss — a miss is found: false with guidance, never an error
  • A web-features id spanning more than one BCD key omits the per-key fields (support, status, limiting_browser, mdn_url, spec_urls) and returns compat_keys to re-call with
  • Typed failure: invalid_feature_input (whitespace-only feature)

browsercompat_check_baseline tool

  • Up to 20 BCD keys or web-features ids per call, 1–200 characters each; one result per entry, in input order
  • Each result carries Baseline state and dates, limiting_browser, deprecated / experimental / discouraged, and usage_percent_excluded alongside the usage_source it is a share of
  • usage_percent_excluded is absent — never zero — when the feature reaches no caniuse id
  • all_widely_available answers the Baseline question alone: every entry resolved at widely, one miss forces it false, and deprecation does not enter it
  • Typed failure: invalid_feature_input (a whitespace-only entry)

browsercompat_search_features tool

  • query 1–100 characters: a plain name, a keyword, or code notation such as Array.prototype.at, display: grid, or <dialog>
  • Optional filters, combinable: namespace (one of the 12 BCD namespaces), baseline (widely | newly | limited | not_mapped), group (a web-features group, nested groups included), and snapshot (an ECMAScript edition such as ecmascript-2023)
  • limit 1–50, default 10, and offset (default 0) to page through the full ranking; nextOffset is present while matches remain
  • Every hit carries matched_on, the field that matched, so the six-tier ranking is inspectable rather than a score; path_suffix marks a key whose trailing segments match the dotted or property-value notation typed
  • support_summary is one line across the seven Baseline core browsers, with — for unsupported and ? for unknown
  • Zero hits are a successful empty result plus a notice naming which filter to drop; totalCount counts every match, and an offset past it returns an empty page with a notice
  • Typed failures: invalid_query (a query that normalizes to zero tokens), unknown_group, unknown_snapshot

browsercompat_compare_support tool

  • Up to 20 features against a required targets browserslist query (defaults, > 0.5%, last 2 versions) — required so browserslist never falls back to config in the server's working directory
  • verdict per feature: clears | fails | inconclusive | miss | ambiguous; failing_targets names each failing target with the verdict behind it (partial, prefixed, flagged, removed, unsupported, preview_only)
  • unchecked_targets lists every target the server declined to judge, with no_bcd_browser | unknown_version | no_bcd_data; all_clear requires that list to be empty
  • target_coverage_percent and unchecked_coverage_percent give the caniuse-derived traffic share of the evaluated and unevaluated tokens
  • Typed failures: invalid_target_query, no_targets_resolved, invalid_feature_input

Data sources

PackageVersionLicenseSupplies
@mdn/browser-compat-data^8.1.2CC0-1.0Per-browser support, standards status, MDN and specification links
web-features^3.39.0Apache-2.0Baseline state and dates, discouraged flags, groups, ECMAScript snapshots
caniuse-lite^1.0.30001810CC-BY-4.0Usage weighting, plus feature titles for the search index
browserslist^4.29.0MITTarget query resolution and coverage figures

CC BY 4.0 requires attribution wherever the caniuse data travels, so every response carrying a usage figure carries this string: Usage data from caniuse.com, © Can I Use contributors, CC BY 4.0. Figures are a share of the ~96.7% of global traffic caniuse tracks. Full license texts and notices are in THIRD_PARTY_NOTICES.md.


Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

Browser-compat-specific:

  • All four datasets are bundled and loaded in process — no runtime network calls, no API key, no rate limit, and nothing to configure
  • Baseline is read per browser-compat-data key from status.by_compat_key, never rolled up from the feature level, because keys under one feature legitimately disagree
  • One shared resolver behind every tool: exact BCD key, then web-features id, then a moved redirect, and only under resolve: true the search index's best exact matches, when they name one feature
  • Target versions are ordered by browser-compat-data's release index rather than parsed version strings, with the caniuse spellings normalized both directions (safari 16.0 ↔ 16, samsung 20 ↔ 20.0)

Agent-friendly output:

  • Every response echoes data_version — the version of each bundled dataset behind the answer, since a pinned snapshot goes stale on exactly the newest features
  • A verdict is never claimed for a browser that was not evaluated: unknown support moves the target into unchecked_targets and the feature to inconclusive
  • Misses are results, not failures — found: false with guidance naming the next call, and typed error reasons carrying recovery hints for the input a caller has to fix
  • Usage figures state the population they are a share of, and carry the caniuse attribution on every response that reports one

Getting started

Public Hosted Instance

A public instance is available at https://browser-compat.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:

{
  "mcpServers": {
    "browser-compat-mcp-server": {
      "type": "streamable-http",
      "url": "https://browser-compat.caseyjhand.com/mcp"
    }
  }
}

Self-Hosted / Local

Add the following to your MCP client configuration file:

{
  "mcpServers": {
    "browser-compat-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/browser-compat-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "browser-compat-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/browser-compat-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with Docker:

{
  "mcpServers": {
    "browser-compat-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT_TYPE=stdio",
        "ghcr.io/cyanheads/browser-compat-mcp-server:latest"
      ]
    }
  }
}

For Streamable HTTP, set the transport and start the server:

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp

Prerequisites

  • Bun v1.4.0 or higher (or Node.js v24+).
  • No API keys, accounts, or network access required — every dataset ships with the package.

Installation

  1. Clone the repository:
git clone https://github.com/cyanheads/browser-compat-mcp-server.git
  1. Navigate into the directory:
cd browser-compat-mcp-server
  1. Install dependencies:
bun install
  1. Configure environment (optional):
cp .env.example .env
# edit .env if you want to override transport or logging defaults

Configuration

There are no server-specific environment variables: no API keys, no base URLs, and deliberately no browserslist configuration variable — the target query is always a tool input rather than ambient state. Only the framework transport settings apply.

VariableDescriptionDefault
MCP_TRANSPORT_TYPETransport: stdio or http.stdio
MCP_HTTP_PORTPort for the HTTP server.3010

See .env.example for the full list of optional framework overrides.


Running the server

Local development

# One-time build
bun run rebuild

# Run the built server
bun run start:stdio
# or
bun run start:http
bun run devcheck   # Lint, format, typecheck, security
bun run test       # Vitest test suite
bun run lint:mcp   # Validate MCP definitions against spec

Docker

docker build -t browser-compat-mcp-server .
docker run --rm -p 3010:3010 browser-compat-mcp-server

The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/browser-compat-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.


Project structure

DirectoryPurpose
src/index.tscreateApp() entry point — registers the tools and warms the datasets.
src/data/The browserslist agent to browser-compat-data browser map.
src/mcp-server/tools/Tool definitions (*.tool.ts) and the output shapes they share.
src/services/bcd, baseline, targets, search, and data-version services over the bundled datasets.
src/types/Ambient module declaration for caniuse-lite, which ships no types.
tests/Vitest suites mirroring src/.
docs/design.md — the surface, the data shapes behind it, and the decisions log.
changelog/Per-version changelog files.

The generated file tree is docs/tree.md.


Development guide

See CLAUDE.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage
  • Register new tools directly in src/index.ts
  • Data integrity: read the bundled datasets as they are and preserve their uncertainty; never fabricate a support fact the data does not carry

Contributing

Issues are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.

Installation

Source-derived launch command. Check the maintainer’s required arguments and credentials before running:

bash
npx -y @cyanheads/browser-compat-mcp-server

Set up in your AI client

Merge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.

json
{
  "mcpServers": {
    "io-github-cyanheads-browser-compat-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "@cyanheads/browser-compat-mcp-server"
      ]
    }
  }
}

Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.

Claude Desktop setup reference

Package

@cyanheads/browser-compat-mcp-servernpm

Compatible MCP Clients

io.github.cyanheads/browser-compat-mcp-server works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.

  • Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.
  • Cursor~/.cursor/mcp.jsonRestart Cursor for changes to take effect.
  • VS Code.vscode/mcp.jsonReload VS Code window for changes to take effect.
  • Windsurf~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect.
  • Claude Code.mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.

Learn More