About pokeapi-mcp-server
pokeapi-mcp-server exposes Pokémon game data from PokéAPI v2 for clients and agents. It combines detailed Pokémon profiles, filtered searches, and computed dual-type matchups through MCP tools and resources.
Key features
- 01Retrieve full Pokémon profiles and forms
- 02Filter by generation, type, Pokédex, or egg group
- 03Compute dual-type effectiveness
- 04Look up moves, abilities, items, and natures
Use cases
- 01Inspect a Pokémon’s stats, abilities, and evolution
- 02Find Pokémon from a generation or egg group
- 03Check defensive multipliers for dual-type Pokémon
MCP support
It provides seven tools and two resources over MCP, with STDIO and Streamable HTTP transports. The interface covers Pokémon records and related game data from PokéAPI v2.
Configuration
Remote servers need no local install. Pick your client, then copy the config or install in one click.
https://pokeapi.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-pokeapi https://pokeapi.caseyjhand.com/mcp{"mcpServers":{"cyanheads-pokeapi":{"type":"http","url":"https://pokeapi.caseyjhand.com/mcp"}}}Open in Cursor{"servers":{"cyanheads-pokeapi":{"type":"http","url":"https://pokeapi.caseyjhand.com/mcp"}}}Open in VS Code{"mcpServers":{"cyanheads-pokeapi":{"type":"http","url":"https://pokeapi.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-pokeapi":{"serverUrl":"https://pokeapi.caseyjhand.com/mcp"}}}Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.
Tools
7| Parameter | Type | Required | Description |
|---|---|---|---|
| identifier | string | Yes | Pokémon name (lowercase hyphenated, e.g. "bulbasaur", "charizard-mega-x") or PokéAPI Pokémon-record ID as a string (e.g. "1", "10034"). A species name (e.g. "deoxys") resolves to its default variety. |
| game_version | string | No | PokéAPI version name to filter flavor text (e.g. "sword", "red", "scarlet"). Falls back to the most recent English entry when the version is not found. |
| include_moves | boolean | No | Include the full learnable-move summary. Defaults to false because the list is large (100–200+ moves). |
Details
From the project README@cyanheads/pokeapi-mcp-server
Look up Pokémon, moves, abilities, items, natures, and type matchups from PokéAPI v2 via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://pokeapi.caseyjhand.com/mcp
Overview
Pokémon game data from PokéAPI: Pokémon, moves, abilities, items, and natures. Get a complete Pokémon profile in one call (stats, abilities, evolution, sprites), filter by generation, type, pokédex, or egg group, and compute dual-type matchups.
Tools
| Tool | Description |
|---|---|
pokeapi_get_pokemon | Denormalized Pokémon dossier in one call — stats, types, abilities, evolution chain, sprites, and species data |
pokeapi_get_type_matchups | Computed offensive and defensive type effectiveness for a type or Pokémon, with correctly composed dual-type matchups |
pokeapi_get_move | Move details — type, damage class, power, accuracy, PP, priority, stat changes, and effect text |
pokeapi_get_ability | Ability details — effect text and the Pokémon that have it, with hidden-ability flag and slot |
pokeapi_get_item | Item details — effect text, category, versioned prices, fling power, attributes, and common holders |
pokeapi_get_nature | Nature details — stat boost/penalty and berry flavor preferences; lists all 25 when called without an identifier |
pokeapi_find_pokemon | Filter Pokémon by generation, type, pokédex, or egg group, with name-token matching and pagination |
Resources
| Resource | Description |
|---|---|
pokeapi://pokemon/{identifier} | Pokémon dossier by name or PokéAPI Pokémon-record ID — same payload as pokeapi_get_pokemon without moves |
pokeapi://type/{typeName} | Type damage relations — raw multiplier table, offensive and defensive |
All resource data is also reachable via tools.
Capability reference
pokeapi_get_pokemon tool
- Accepts a lowercase-hyphenated name or numeric PokéAPI Pokémon-record ID as
identifier; an unknown entry returnsnot_found. A species name resolves to its default variety (deoxysreturnsdeoxys-normal, withresolvedFromSpecies: "deoxys"). - Returns stats, types, ability effects, sprites, evolution chain (every
evolutionDetailsalternative), varieties, capture and growth rates, gender ratio, and legendary/mythical flags in one dossier. include_moves(defaultfalse) adds the move summary;moveCountis always returned.game_versionselects flavor text and falls back to the most recent English entry.
pokeapi_get_type_matchups tool
- Requires exactly one of
type(type name) orpokemon(name or PokéAPI Pokémon-record ID); unknown entries returnnot_found. - Species names resolve to their default variety (
deoxysusesdeoxys-normal);resolvedPokemonandresolvedFromSpeciesreport the match and are null for direct type queries. - Returns
offensiveRelations(null for dual-type Pokémon) anddefensiveMatchups, with dual-type defenses composed and immunity taking precedence. composedMultiplierscarries 0, 0.25, 0.5, 1, 2, or 4 per attacking type; absent types also deal 1×.
pokeapi_get_move tool
- Accepts a lowercase-hyphenated move name or numeric ID; an unknown entry returns
not_found. - Returns type, damage class, power, accuracy, PP, priority, target, stat changes, and secondary-effect chance, plus full and short English effect text
include_learners(defaultfalse) adds the list of Pokémon that can learn the move.learnersIncludeddistinguishes an unrequested list from a requested list with no known learners.
pokeapi_get_ability tool
- Accepts a lowercase-hyphenated ability name or numeric ID
- Returns full and short English effect text, the generation introduced, and every Pokémon that has the ability, with its hidden-ability flag and slot
not_foundwhen the identifier resolves to no ability
pokeapi_get_item tool
- Accepts a lowercase-hyphenated item name or numeric ID
- Returns category, fling power, attributes (holdable, consumable, etc.), sprite URL, effect text, and Pokémon that commonly hold it
priceslists every version/currency row (versionGroup,currency,purchasePrice,sellPrice); null means not purchasable/sellable there, and an empty list means no price records.costis the legacy Pokédollar cost, or null.not_foundwhen the identifier resolves to no item
pokeapi_get_nature tool
identifier(name or ID 1–25) is optional — omit it to return all 25 natures at once (isListAll: true)- Each entry carries the boosted stat, reduced stat, and liked/disliked berry flavor — all null for the 5 neutral natures
not_foundwhen a provided identifier resolves to no nature
pokeapi_find_pokemon tool
- Requires at least one of
generation,type,pokedex, andegg_group, combined with AND logic;query(at most 100 characters) adds per-token name matching within them. Unrecognized category names returninvalid_filter. - Returns
idandnameentries for follow-uppokeapi_get_pokemoncalls, withtotalCountbefore paging. Type-only searches include forms; generation, pokédex, and egg-group filters return species. IDs are PokéAPI IDs, not dex numbers. appliedFiltersechoes the filters, query tokens,limit, andoffsetthat were applied. A call with no category returns no entries and a notice saying one is required.limit(default 50) andoffset(default 0) paginate the filtered set. A page past the last match keepstotalCountand advisesoffset: 0; zero matches advise relaxing the filters.
pokeapi://pokemon/{identifier} resource
- Same payload as
pokeapi_get_pokemonwithinclude_movesfixed tofalse identifieris a name or PokéAPI Pokémon-record ID, including form IDs; a species name resolves to its default varietynot_foundwhen the identifier matches no Pokémon record and no species
pokeapi://type/{typeName} resource
- Returns the raw offensive and defensive damage-relation multiplier table for one type
typeNameis one of the 18 canonical Pokémon typesnot_foundwhen the type name doesn't exist in PokéAPI
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.
PokéAPI-specific:
- Keyless and read-only — no API key, no auth, no configuration required to run
- Graph-walk consolidation —
pokeapi_get_pokemonfans out across/pokemon,/pokemon-species,/evolution-chain, and N/abilityendpoints in two parallel tiers, returning one object - Aggressive caching — PokéAPI data is static game data; responses are cached with a configurable TTL (default 6 h) to respect PokéAPI's fair-use policy
- Input normalization — accepts lowercase-hyphenated names or numeric IDs; trims, lowercases, and hyphenates whitespace. A blank identifier or one over 100 characters returns
not_found(invalid_filterfor a search filter) without an upstream request - English-first —
effect_entriesandflavor_text_entriesare always filtered tolanguage.name === 'en'; absent entries surface asnullrather than a foreign-language string
Agent-friendly output:
- Dual-type composition —
pokeapi_get_type_matchupscomputes the effective matchup matrix from raw damage relations, so agents get a direct answer rather than raw tables to multiply - Variant surface —
pokeapi_get_pokemonlists all form variants so agents can identify and re-call with specific forms (Alolan, Galarian, Mega, Gigantamax) - Nullable details — missing descriptions, sprites, holders, and learners are stated explicitly in text and structured results rather than omitted
Getting started
Public Hosted Instance
A public instance is available at https://pokeapi.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"pokeapi-mcp-server": {
"type": "streamable-http",
"url": "https://pokeapi.caseyjhand.com/mcp"
}
}
}
Self-Hosted / Local
No API key required. Add the following to your MCP client configuration file:
{
"mcpServers": {
"pokeapi-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/pokeapi-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"pokeapi-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/pokeapi-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"pokeapi-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/pokeapi-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 key required — PokéAPI is fully public.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/pokeapi-mcp-server.git
- Navigate into the directory:
cd pokeapi-mcp-server
- Install dependencies:
bun install
- Configure environment (optional):
cp .env.example .env
# All vars are optional — the server works with defaults
Configuration
| Variable | Description | Default |
|---|---|---|
POKEAPI_BASE_URL | PokéAPI base URL — override for local mirrors or proxies. | https://pokeapi.co/api/v2 |
POKEAPI_CACHE_TTL_SECONDS | How long to cache PokéAPI responses (seconds). | 21600 (6 h) |
POKEAPI_REQUEST_TIMEOUT_MS | Per-request timeout in milliseconds. | 10000 |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_SESSION_MODE | HTTP session mode: auto, stateful, or stateless. | stateless |
MCP_HTTP_PORT | Port for HTTP server. | 3010 |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (RFC 5424). | info |
LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
LOG_TOOL_FAILURE_PAYLOADS | Log failed-call input and result, redacted by key name and capped at LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES (default 16384). Secrets inside free-form values are not redacted. | false |
OTEL_ENABLED | Enable OpenTelemetry instrumentation. | false |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT | OTLP log export endpoint. | Unset |
See .env.example for the full list of optional overrides.
Self-hosting for high-volume use
PokéAPI's Fair Use Policy asks consumers to cache aggressively and points high-volume deployments toward running a local instance. This server already caches responses for 6 hours by default (POKEAPI_CACHE_TTL_SECONDS), which covers most workloads. For hosted or batch-heavy deployments, run the official PokéAPI Docker image locally and point POKEAPI_BASE_URL at it — the server switches transparently.
Running the server
Local development
-
Build and run:
bun run rebuild bun run start:stdio # or bun run start:http -
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Offline Vitest suite with deterministic fetch fixtures bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t pokeapi-mcp-server .
docker run --rm -p 3010:3010 pokeapi-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/pokeapi-mcp-server. Build with --build-arg OTEL_ENABLED=false to omit OpenTelemetry peer dependencies.
Project structure
| Path | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools, resources, and inits services. |
src/config/ | Server-specific env var parsing with Zod (server-config.ts). |
src/mcp-server/tools/ | Tool definitions (*.tool.ts). |
src/mcp-server/resources/ | Resource definitions (*.resource.ts). |
src/services/pokeapi/ | PokeApiService — typed fetch methods, caching, retry, timeout. |
tests/ | Vitest test suite mirroring src/. |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — catch typed upstream errors only to map a declared
errors[]contract withctx.fail(...) - Use
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storage (and caching) - Register new tools and resources in the
createApp()arrays insrc/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
Apache-2.0 — see LICENSE for details.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.