# Give your AI agent Pokémon card prices with MCP

> Eight read-only MCP tools for agents: search, lookups, dated EUR and USD quotes, sets, vocabularies, photo recognition. One-line install, and how it is built.

- **Published**: 2026-09-26
- **Updated**: 2026-09-26
- **Tags**: mcp

Source: https://pokemontcgapi.com/blog/give-your-ai-agent-card-prices-with-mcp

An agent that can answer "what is a Japanese Umbreon VMAX alt art worth in Europe right now" needs three things: a way to find the card, a way to read its quotes, and the discipline not to invent either. The Model Context Protocol gives the first two a standard shape, so a Claude, Cursor or VS Code session can call our API without anyone writing a client. This article is how our server is put together, and where the design choices come from.

The server is `@pokemontcgapi/mcp` on npm, listed in the official MCP registry as `com.pokemontcgapi/mcp`. It speaks stdio, runs on Node 20 or newer, and needs one environment variable, `PTCG_API_KEY`, which a [trial key](https://pokemontcgapi.com/free-api-key) fills without a card.

## Install in one line

Claude Code:

```bash
claude mcp add pokemontcgapi --env PTCG_API_KEY=$PTCG_API_KEY -- npx -y @pokemontcgapi/mcp
```

Claude Desktop, in `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "pokemontcgapi": {
      "command": "npx",
      "args": ["-y", "@pokemontcgapi/mcp"],
      "env": { "PTCG_API_KEY": "your-key" }
    }
  }
}
```

Cursor and VS Code use the same command with their own file layout; the [MCP page](https://pokemontcgapi.com/mcp) has the four configurations with the notes that matter, such as the `inputs` block that keeps the key out of a committed VS Code file. Then ask the agent for a card, and watch which tool it picks.

## Eight tools, not one per endpoint

The API has about two dozen routes. The server exposes eight tools, and the number is a design decision rather than a shortcut. The tool list sits in the model's context on every turn, whether or not the conversation is about cards, so the whole surface is kept to roughly eleven kilobytes. And each tool is shaped like a question rather than like a route, because a tool per route forces the model to chain four calls to answer one thing, and every link in that chain is a place to make a mistake.

| Tool | Answers |
| --- | --- |
| `ptcg_search_cards` | Charizard cards from Japanese sets, cards by an illustrator, everything in a release window. |
| `ptcg_get_cards` | Up to 100 ids in one call. Canonical prefixes bind to their set; unresolved ids are reported with verified alternatives when the API provides them. |
| `ptcg_get_card_prices` | Every current observation for a card, each with its printing, grade, sample size and date. |
| `ptcg_list_sets` | Every Japanese set released in 2024, in one call, with release dates and card counts. |
| `ptcg_get_reference` | The exact strings for types, supertypes and rarities, so a filter is never guessed. |
| `ptcg_list_artists` | Illustrators with a card count, deduplicated across thirty years of printings. |
| `ptcg_get_catalogue_status` | Live counts per print region and an explicit statement of what is NOT in the data, so an agent is told rather than left to infer. |
| `ptcg_identify_card_from_image` | A photograph in, ranked candidates out, and an explicit refusal to pick when two printings share the illustration. 25 credits a call, and included from the Growth plan up. |

Seven of the eight need the key. The one exception is `ptcg_get_reference`, which reads the public vocabularies. When the key is absent, the server still starts and lists its tools, and the seven calls come back with a message that says exactly which variable to set and where to get a key, rather than a bare authentication error. A model can act on that; a human can copy it.

## Tables, not JSON

Every tool answers twice. The text the model reads is an aligned table, because a table costs roughly forty percent of the tokens of the equivalent JSON and the model reads it at least as well. The exact structure goes into `structuredContent` beside it, which a client can consume directly when it wants the data rather than the prose. Nothing is lost; the model just does not pay for braces and quotes.

The server also caps every list at fifty rows, well under the two hundred and fifty the API allows, because two hundred and fifty rows do not survive a context window. A search that needs more is a search that should be narrowed, and the tool description says so. The cursor for the next page comes from the URL the API built; the server never reconstructs one, which is the failure mode cursor signatures exist to prevent.

## Prices with their paperwork attached

`ptcg_get_card_prices` returns every current observation for a card, one row each, with source, basis, currency, printing, grade, sample size and the `as_of` date. The model sees a Cardmarket asking price in EUR and a TCGplayer guide figure in USD as two rows, and the composite index as a third, so it can say "the European figure is X as of Tuesday" instead of a number with no provenance. The rule is the same one the API follows everywhere: [a price is a row, not a number](https://pokemontcgapi.com/blog/how-we-compute-eur-and-usd-card-prices). The call costs 2 credits; searches and lookups cost 1 credit.

The graded rows and the movers depend on the plan the key is on. When the plan withholds something, the tool result says what was held back and where the account owner can change that, on the first line, before the data. That sentence is meant to be shown verbatim and not retried: a model that retries a commercial refusal burns credits on the same answer.

## The one tool that is not free to retry

`ptcg_identify_card_from_image` takes a photo and returns ranked candidates, or an explicit refusal when reprints share the same artwork and the photo cannot tell them apart. It costs 25 credits a call and is included from the Growth plan up. It is also the only tool annotated as not idempotent, because the same photo costs 25 credits every time it is sent, and a client must not retry it on its own. All eight tools carry `readOnlyHint: true` and `destructiveHint: false`: nothing here writes.

## Telling the agent what is not there

`ptcg_get_catalogue_status` exists for one reason: models fill gaps with plausible text. The tool measures the catalogue live, starting from the public status route and then reading one set per print region, and reports what the catalogue does and does not contain: no game text on Japanese cards, no sets printed in Korea, price coverage thinner on the Japanese side. An agent that has read that answer says "I do not have the attack text for this Japanese card" instead of inventing one. It is the tool we would keep if we could keep only two.

- Use the MCP tools for bounded, interactive questions. For a full catalogue import, use the REST API directly and follow `links.next`; the server's README says the same and links the paging loop.
- Keep the key in the client's environment or its secret input, never in a prompt. A key pasted into a conversation is a key you rotate.
- Read `as_of` on every price row the agent quotes to you. The API serves settled figures with a delay, and the date is part of the answer.

## What we do not know yet

Whether the server brings anyone to the API. Signups carry an attribution that says a conversation on an assistant sent them, not which answer or whether a tool call was involved. Half of last month's signups came from assistant answers; how many of those had the server installed, we cannot tell. If you measure MCP-driven adoption better than that, we would like to hear how.

> **Where to go next**
>
> The [MCP page](https://pokemontcgapi.com/mcp) has every client configuration and the tool list with arguments. The server is open source; the package README has the same install steps and a section on what the API does not have.
