@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.
7 Tools • 2 Resources
Tools
Seven tools covering the full PokéAPI v2 surface — a flagship consolidation tool, a computed matchup tool, single-resource lookups, and a filter tool:
pokeapi_get_pokemon | Denormalized Pokémon dossier in one call: base stats, types, abilities with effect text, height/weight, evolution chain, learnable moves, sprites, species flavor text, and variant list |
pokeapi_get_type_matchups | Computed offensive and defensive type effectiveness — for a type name or Pokémon identifier; correctly composes dual-type matchups |
pokeapi_get_move | Move details: type, damage class, power, accuracy, PP, priority, target, stat changes, status-effect chance, and full English effect text |
pokeapi_get_ability | Ability details: full and short English effect text, and the Pokémon that have it (with hidden-ability flag and slot) |
pokeapi_get_item | Item details: effect text, category, cost, fling power, attributes, and Pokémon that commonly hold it |
pokeapi_get_nature | Nature details: stat boost/penalty, preferred and disliked berry flavor. Returns all 25 natures when called without an identifier |
pokeapi_find_pokemon | Filter Pokémon by generation, type, pokédex, or egg group; also resolves fuzzy name queries to canonical entries |
pokeapi_get_pokemon
The flagship tool — fans out across the PokéAPI resource graph in parallel and returns one denormalized dossier, replacing 10–30 sub-resource GETs.
- Fetches
/pokemon, /pokemon-species, /evolution-chain, and each /ability in a two-tier parallel fan-out
- Includes sprites (with
official-artwork high-quality art URL), is_legendary, is_mythical, capture_rate, growth_rate, gender_rate
include_moves (default false) — set to true for a summarized learnable-move list filtered to the latest generation
game_version string to select flavor text by game (e.g. "sword", "red") — silently falls back to first available when no match
- Surfaces the variant list so callers can re-call with a specific form name (regional forms, Gigantamax, Mega, etc.)
pokeapi_get_type_matchups
Computed type effectiveness — pass a type name or Pokémon identifier to get the full offensive and defensive breakdown with multiplier values.
- For dual-type Pokémon: composes both type defensive relations correctly (immune in either type wins)
- Returns
superEffective, resistant, and immune lists for both offense and defense
- Accepts either
type (type name) or pokemon (name or dex number) — exactly one required
pokeapi_find_pokemon
Filter Pokémon by multiple criteria — returns names and dex numbers for follow-up pokeapi_get_pokemon calls.
- Filters:
generation (e.g. "generation-i"), type (e.g. "fire"), pokedex (e.g. "kanto"), egg_group (e.g. "fairy")
query parameter for fuzzy name search
- Pagination via
limit and offset
Resources and prompts
| Resource | pokeapi://pokemon/{identifier} | Pokémon dossier by name or dex number — same payload as pokeapi_get_pokemon without moves |
| Resource | pokeapi://type/{typeName} | Type damage relations — raw multiplier table, offensive and defensive |
All resource data is also reachable via tools.
Features
Built on @cyanheads/mcp-ts-core:
- Declarative tool and resource definitions — single file per primitive, framework handles registration and validation
- Unified error handling — handlers throw, framework catches, classifies, and formats
- Pluggable auth:
none, jwt, oauth
- Swappable storage backends:
in-memory, filesystem, Supabase, Cloudflare KV/R2/D1
- Structured logging with optional OpenTelemetry tracing
- STDIO and Streamable HTTP transports
PokéAPI-specific:
- Keyless and read-only — no API key, no auth, no configuration required to run
- Graph-walk consolidation —
pokeapi_get_pokemon fans out across /pokemon, /pokemon-species, /evolution-chain, and N /ability endpoints in two parallel tiers, returning one object
- Aggressive caching — PokéAPI data is static game data; responses are cached in
ctx.state with a configurable TTL (default 6 h) to respect PokéAPI's fair-use policy
- Input normalization — accepts lowercase-hyphenated names or numeric IDs; strips and lowercases user input before fetching
- English-first —
effect_entries and flavor_text_entries are always filtered to language.name === 'en'; absent entries surface as null rather than a foreign-language string
Agent-friendly output:
- Dual-type composition —
pokeapi_get_type_matchups computes the effective matchup matrix from raw damage relations, so agents get a direct answer rather than raw tables to multiply
- Variant surface —
pokeapi_get_pokemon lists all form variants so agents can identify and re-call with specific forms (Alolan, Galarian, Mega, Gigantamax)
- Sparse-safe nullable fields — upstream absent fields surface as
null rather than crashing or returning a fabricated default
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
Prerequisites
- Bun v1.3.0 or higher (or Node.js v24+).
- No API key required — PokéAPI is fully public.
Installation
git clone https://github.com/cyanheads/pokeapi-mcp-server.git
- Navigate into the directory:
cd pokeapi-mcp-server
bun install
- Configure environment (optional):
cp .env.example .env
Configuration
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_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 |
OTEL_ENABLED | Enable OpenTelemetry instrumentation. | false |
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
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
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 — no
try/catch in tool logic
- Use
ctx.log for request-scoped logging, ctx.state for tenant-scoped storage (and caching)
- Register new tools and resources via the barrels in
src/mcp-server/*/definitions/index.ts
- Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
Apache-2.0 — see LICENSE for details.