- Nix 92.7%
- Rust 7.3%
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.nix | ||
| Cargo.toml | ||
| default.nix | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
monmcp
A Pokemon MCP server. Fetches data from PokeAPI and caches it locally in SQLite so the API is only hit once per resource. Designed to run locally over stdio, making it easy to connect to Claude or any MCP-compatible client for Pokemon team-building.
Features
- 9 MCP tools covering Pokemon, moves, abilities, items, natures, types, and team coverage
- Permanent local cache — responses are stored in SQLite and never re-fetched unless invalidated
- Cache management CLI — invalidate individual entries, entire resource kinds, or everything at once
- No network dependency after first fetch — fully offline once data is cached
Installation
cargo install --path .
Or build directly:
cargo build --release
# Binary: ./target/release/monmcp
Usage
Start the MCP server (default)
monmcp
# or equivalently:
monmcp serve
Logs go to stderr; stdout is reserved for the JSON-RPC channel.
Cache management
| Command | Description |
|---|---|
monmcp cache stats |
Show row counts for every cache table |
monmcp cache invalidate |
Clear all cached data |
monmcp cache invalidate --resource <KIND> |
Clear all entries for one resource kind |
monmcp cache invalidate --resource <KIND> --key <NAME_OR_ID> |
Remove one specific cached entry |
Resource kinds: pokemon, ability, move, type, item, nature
# Show how much is cached
monmcp cache stats
# Clear everything
monmcp cache invalidate
# Clear only move cache
monmcp cache invalidate --resource move
# Remove a single entry
monmcp cache invalidate --resource pokemon --key pikachu
MCP Tools
| Tool | Input | Description |
|---|---|---|
get_pokemon |
name_or_id: string |
Stats, types, abilities, moves, and sprite. Requires an exact PokeAPI name slug (e.g. "pikachu", "zygarde-50") or numeric dex ID — names are NOT fuzzy-matched. Use search_pokemon first to resolve the canonical slug if unsure. |
get_ability |
name_or_id: string |
Effect description and list of Pokemon with this ability. |
get_move |
name_or_id: string |
Power, accuracy, PP, type, damage class, and effect. |
get_type_matchups |
type_name: string |
Full damage relation table (2×/0.5×/0× both ways). |
search_pokemon |
query: string, limit?: number |
Search by name substring; returns canonical slugs + dex IDs. Use to resolve ambiguous names before calling get_pokemon or check_team_coverage. First call fetches and caches the full ~1300-entry index. |
get_item |
name_or_id: string |
Cost, category, effect, and flavor text. |
get_nature |
name_or_id: string |
Increased/decreased stat (+10%/−10%) and flavor preferences. |
list_pokemon_by_type |
type_name: string |
All Pokemon that have the given type. |
check_team_coverage |
names_or_ids: string[] |
Defensive and offensive type coverage for a team of up to 6 Pokemon. Requires exact PokeAPI slugs or numeric IDs — use search_pokemon to resolve slugs for multi-form Pokemon. |
All name_or_id / type_name inputs accept either a lowercase name ("pikachu", "fire") or a numeric ID ("25", "10").
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
MONMCP_DB_PATH |
No | $XDG_DATA_HOME/monmcp/cache.sqlite3 |
Path to the SQLite cache database. Created automatically if missing. |
XDG_DATA_HOME |
No | ~/.local/share |
Fallback used to compute the default DB path when MONMCP_DB_PATH is not set. |
RUST_LOG |
No | monmcp=info |
Log filter passed to tracing-subscriber. Example: monmcp=debug. |
Nix
A flake.nix is provided. Exposes packages.x86_64-linux.default and overlays.default.
Build
nix build
NixOS / Home Manager
Add as flake input:
inputs.monmcp.url = "git+https://git.cozygalvinism.dev/cozyGalvinism/monmcp";
Apply overlay so pkgs.monmcp is available:
nixpkgs.overlays = [ inputs.monmcp.overlays.default ];
Install the binary:
home.packages = [ pkgs.monmcp ];
Integrate with mcp-servers-nix:
mcp-servers.settings.monmcp = {
command = "${pkgs.monmcp}/bin/monmcp";
args = [];
};
Claude Desktop / Claude Code integration
Add to your MCP config (e.g. ~/.claude/mcp.json):
{
"mcpServers": {
"monmcp": {
"command": "/path/to/monmcp",
"args": ["serve"]
}
}
}
Then ask Claude things like:
- "What are Garchomp's base stats and moves?"
- "Build me a balanced team with good type coverage."
- "Which Pokemon learn Earthquake?"
Architecture
src/
├── main.rs # Clap CLI (serve / cache subcommands)
├── config.rs # Env-based configuration
├── error.rs # AppError (thiserror)
├── db/
│ ├── mod.rs # SQLite pool init, WAL mode
│ ├── schema.sql # 6 cache tables + pokemon_index
│ └── cache.rs # CacheStore — get/put/invalidate/search
├── pokeapi/
│ ├── mod.rs # RustemonClient builder (MokaManager)
│ ├── pokemon.rs # fetch_by_name / fetch_by_id / fetch_all_entries
│ ├── ability.rs
│ ├── move_.rs
│ ├── type_.rs
│ ├── item.rs
│ └── nature.rs
├── service/
│ ├── mod.rs # PokeService — cache-first lookup for all resources
│ └── shape.rs # JSON projection helpers (trim raw blobs to compact output)
└── mcp/
├── mod.rs # StdioTransport + server startup
├── handler.rs # ServerHandler impl
└── tools.rs # 9 tool structs with #[mcp_tool] + tool_box!
Cache entries are stored as raw JSON blobs keyed by both name and numeric ID, so either lookup hits the cache. The pokemon_index table is populated lazily on the first search_pokemon call.