Skip to main content
Glama
README.md
# Models MCP

[![CI](https://github.com/QAInsights/models-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/QAInsights/models-mcp/actions/workflows/ci.yml)
[![Catalog drift](https://github.com/QAInsights/models-mcp/actions/workflows/catalog-drift.yml/badge.svg)](https://github.com/QAInsights/models-mcp/actions/workflows/catalog-drift.yml)

Search, compare, and inspect AI models by pricing, context window, and capabilities. An MCP server over the [models.dev](https://models.dev) catalog (`models.dev/api.json`), so your agent always has current model data without you hand-maintaining a list.

models.dev itself doesn't ship an MCP server, just a JSON API and a TypeScript SDK for reading it. This fills that gap.

Runs two ways from the same tool code:

- **stdio** (`src/index.ts`) for local MCP clients
- **Cloudflare Worker** (`src/worker.ts`) as a remote Streamable HTTP endpoint at `/models-mcp`

## Tools

| Tool | What it does |
|---|---|
| `list_providers` | Lists every provider (anthropic, openai, google, ...) with model counts |
| `find_models` | Filters models by name, provider, min context window, max input cost, or capability flags (reasoning, tool_call, attachment) |
| `get_model` | Full metadata for one model, by `provider/model` id |
| `compare_models` | Side-by-side diff of 2-6 models on pricing, context, and capabilities |
| `top_models` | Ranks models by cheapest input/output price, largest context, context-per-dollar, or newest release; supports the same filters as `find_models` |
| `estimate_cost` | Computes the USD cost of a request from a model's published per-million-token rates, including cache read/write components |
| `get_provider` | Provider metadata: display name, AI SDK package, API base URL, docs link, and a compact list of its models |
| `refresh_catalog` | Forces a re-fetch, bypassing the 1-hour cache |

All search-style tools (`find_models`, `top_models`) share one filter schema, so filter semantics are identical everywhere. Ranking and estimation exclude models that lack the relevant data (e.g. unpriced local models) rather than guessing.

## Install

```bash
npm install
npm run build
```

## Run standalone over stdio (for testing)

```bash
npm start
```

It speaks MCP over stdio, so you won't see much directly; use the [MCP Inspector](https://github.com/modelcontextprotocol/inspector) to poke at it:

```bash
npx @modelcontextprotocol/inspector node dist/index.js
```

## Host on Cloudflare Workers

The Worker entry (`src/worker.ts`) serves the same tools over Streamable HTTP at `/models-mcp`, with:

- **Catalog caching** in the Workers Cache API (`caches.default`) with a 1-hour TTL, shared across requests and isolates.
- **Per-IP rate limiting** via a Workers rate limiting binding: 60 requests/minute per IP, enforced per Cloudflare location. Excess requests get `429` with `Retry-After: 60`.

```bash
# local dev at http://localhost:8787/models-mcp
npm run dev:worker

# deploy
npm run deploy
```

After deploy, the canonical endpoint is `https://mcp.dosa.dev/models-mcp`. The generated `https://models-mcp.<your-subdomain>.workers.dev/models-mcp` URL stays live as a fallback.

Point MCP clients at it:

Claude Code:

```bash
claude mcp add --transport http models-mcp https://mcp.dosa.dev/models-mcp
```

Generic client config (anything that speaks Streamable HTTP):

```json
{
  "mcpServers": {
    "models-mcp": {
      "url": "https://mcp.dosa.dev/models-mcp"
    }
  }
}
```

For stdio-only clients (Claude Desktop), bridge with [mcp-remote](https://github.com/geelen/mcp-remote):

```json
{
  "mcpServers": {
    "models-mcp": {
      "command": "npx",
      "args": ["mcp-remote", "https://mcp.dosa.dev/models-mcp"]
    }
  }
}
```

No API keys required anywhere. All data comes from the public `models.dev/api.json` endpoint.

## Try it out

With the dev server running (`npm run dev:worker`), the endpoint is `http://localhost:8787/models-mcp`.

Quick curl (MCP initialize):

```bash
curl -X POST http://localhost:8787/models-mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"manual","version":"1.0"}}}'
```

Expect an SSE response with `serverInfo.name: "models-mcp"`.

MCP Inspector (best for poking at tools interactively):

```bash
npx @modelcontextprotocol/inspector
```

Set Transport Type to Streamable HTTP and URL to `http://localhost:8787/models-mcp`, then call tools from the UI.

Claude Code against the local server:

```bash
claude mcp add --transport http models-mcp-local http://localhost:8787/models-mcp
```

Then ask it something like "which anthropic models cost under $1 per million input tokens?" and watch it reach for `find_models`.

Rate limiting: fire 61 rapid requests at the endpoint and request 61 onwards returns `429` with `Retry-After: 60`.

Things worth trying in the Inspector:

- `find_models` with combined filters, e.g. `maxInputCost: 0.5` together with `minContext: 200000`
- `get_model` with a bare id like `gpt-5.2` (resolves) and with a nonsense id (clean tool error)
- `compare_models` with one invalid id mixed in (it lands under `notFound`)
- The first call fetches the live catalog (~200ms); repeat calls are cache hits

## Tests

```bash
npm test
```

Covers the catalog client (flattening, TTL caching, force refresh, stale-on-failure fallback, id resolution) and all eight tools end-to-end through a real MCP client session over an in-memory transport.

## Notes on the data

- The catalog is cached for 1 hour: in the Workers Cache API when hosted, in process memory over stdio. Call `refresh_catalog` to force an update. If a refetch fails, the last good catalog keeps being served and `refresh_catalog` reports `servedStale: true` so you can tell.
- A daily GitHub Actions workflow (`Catalog drift`) fetches the live `api.json` and sanity-checks it against the flattening logic, since models.dev publishes no versioned schema. It opens a `catalog-drift` issue if upstream changes shape. Run it locally with `npm run build && npm run test:live`.
- models.dev doesn't publish a versioned schema for consumers, so the types in `src/types.ts` are intentionally loose (index signatures preserve any fields not explicitly typed).
- Model ids follow the `provider/model` convention used by the AI SDK and OpenCode, e.g. `anthropic/claude-sonnet-4-5`. `get_model` and `compare_models` also accept a bare model id when it names exactly one model across all providers; if the bare id is ambiguous (common with aggregator providers mirroring first-party models), the tool errors with the list of candidate `provider/model` ids instead of silently picking one. `get_provider` emits full `provider/model` ids so its output round-trips through `get_model` unchanged.

## Possible extensions

- A `list_facets` tool (modalities, tokenizers) similar to what other model-catalog MCPs expose.
- A `test_model` tool that makes a live call through whichever provider key you have configured, for latency/cost sanity checks.
- OAuth or Cloudflare Access in front of the Worker, if you want it private.

TDQS

A4.2/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct operation: listing providers, searching models, fetching details, comparing, refreshing, estimating cost, ranking, and provider metadata. Even where two tools support similar filters, their purposes are clearly differentiated by descriptions.

Naming Consistency4/5

Tool names mostly follow a clear verb_noun pattern such as list_providers, find_models, get_model, and estimate_cost. The exception is top_models, which reads more like a noun phrase than an imperative verb action, a minor deviation from the otherwise consistent convention.

Tool Count5/5

Eight tools is a well-scoped size for a model catalog server. Each tool covers a meaningful workflow without redundancy or bloat, from discovery and search to comparison and cost estimation.

Completeness5/5

The surface covers the full read-only lifecycle of interacting with the models.dev catalog: list, search, detail, compare, rank, and cost estimation, plus provider-level metadata and cache refresh. No obvious dead ends or missing core operations are present.

Maintenance

ActivityMaintained
ResponsivenessNo issues