scryfall-mcp
by as3k
README.md
# scryfall-mcp
An MCP server that wraps the Scryfall API and gives any agent full access to Magic: The Gathering card data — search, rulings, sets, symbols, catalogs, and local deck management with multi-owner support.
Works with Claude Desktop, Pi, Hermes, Cursor, Claude Code, or any MCP client.
---
## What you get
**28 tools.** Full Scryfall API coverage — search, rulings, sets, symbols, catalogs, bulk data, migrations, plus local deck management with multi-owner support, export/import, and card caching.
| Area | Tools |
|------|-------|
| **Card lookup** | `search_cards`, `get_card`, `autocomplete_card`, `get_random_cards`, `get_cards_collection` |
| **Card display** | Shows all faces (transform/adventure/battle), tokens/related cards, game changer flags, EDHREC rank, purchase links, preview info |
| **Rulings** | `get_card_rulings` |
| **Sets** | `list_sets`, `get_set` |
| **Symbols** | `list_card_symbols`, `parse_mana_cost` |
| **Catalogs** | `get_catalog` (creature types, keywords, artists — every canonical list) |
| **API data** | `list_bulk_data`, `get_bulk_data`, `list_card_migrations`, `get_related_cards` |
| **Deck CRUD** | `create_deck`, `list_decks`, `get_deck`, `update_deck`, `delete_deck`, `search_decks` |
| **Deck cards** | `add_card_to_deck`, `remove_card_from_deck` |
| **Deck analysis** | `analyze_deck`, `validate_deck` |
| **Format rules** | `get_format_rules` (13 formats with per-format validation) |
| **Export/Import** | `export_deck` (MTGA/Archidekt format), `import_deck_from_text` (bulk add from text) |
Decks live as JSON files at `~/.config/scryfall-mcp/decks/`. Each deck has an `owner` field — multiple people can manage their own decks from the same server.
Card data is cached locally at `~/.config/scryfall-mcp/cache/cards/` so repeated lookups (same card, same session or across sessions) cost zero API calls. The cache has a 24-hour TTL.
Both paths live **outside your repo clone** — updating the code or switching branches won't touch your data.
---
## Quick start
```bash
git clone <repo-url> scryfall-mcp
cd scryfall-mcp
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python server.py
```
That's it. The server starts on stdio, which is what most MCP clients expect.
---
## Connecting
### Claude Desktop
Add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"scryfall": {
"command": "python3",
"args": ["/absolute/path/to/scryfall-mcp/server.py"]
}
}
}
```
### Pi
Add to your Pi `settings.json` (global or project-local):
```json
{
"mcpServers": {
"scryfall": {
"command": "python3",
"args": ["/absolute/path/to/scryfall-mcp/server.py"]
}
}
}
```
Then `/reload` Pi.
### Hermes
Same pattern — point your Hermes MCP config at the server script.
### Any MCP client via Python
```python
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
server_params = StdioServerParameters(
command="python3",
args=["/path/to/scryfall-mcp/server.py"],
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool("search_cards", {
"query": "c:red t:instant cmc<=2",
})
print(result.content[0].text)
```
---
## Search syntax (the part you'll use most)
Scryfall's search is powerful. Here's the cheat sheet:
```
c:red Color
t:instant Type
o:"draw a card" Oracle text
m:{U}{U} Mana cost
pow>=4 Power
tou<=2 Toughness
s:mkm Set code
f:standard Format legality
id:ub Color identity
r:mythic Rarity
year:2024 Release year
is:transform Layout flag
-t:creature Negation
(t:instant OR t:sorcery) Grouping
```
Combine freely. `c:red t:instant cmc<=1` = cheap red instants.
---
## Deck management
Decks are stored as JSON files in `~/.config/scryfall-mcp/decks/`. One file per deck.
```bash
# Create a deck
python -c "
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def run():
async with stdio_client(StdioServerParameters(command='python3', args=['server.py'])) as (r, w):
async with ClientSession(r, w) as s:
await s.initialize()
r = await s.call_tool('create_deck', {
'name': 'My Deck',
'owner': 'zg',
'format': 'commander'
})
print(r.content[0].text)
asyncio.run(run())
"
```
Or just use the tools directly from your agent — that's the whole point.
### Export to MTG Arena / Archidekt
```bash
# Export a deck in MTGA format (importable into Arena, Archidekt, Moxfield)
python -c "
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def run():
async with stdio_client(StdioServerParameters(command='python3', args=['server.py'])) as (r, w):
async with ClientSession(r, w) as s:
await s.initialize()
r = await s.call_tool('export_deck', {
'deck_id': '<deck-uuid>',
'format': 'mtga'
})
print(r.content[0].text)
asyncio.run(run())
"
```
Output:
```
// My Deck
// Format: commander
// Cards: 100 main + 1 side
// Mainboard
1 Krenko, Mob Boss (JMP) 338
20 Mountain (SLD) 432
4 Lightning Bolt (M10) 123
...
Sideboard
2 Pyroblast (EMA) 141
```
### Import from MTGA text
Paste a deck list into an existing deck:
```
python -c "... call import_deck_from_text with:
deck_id: '<deck-uuid>'
text: |
4 Lightning Bolt (M10) 123
20 Mountain
Sideboard
2 Disenchant
"
```
---
## Options
```bash
python server.py --transport sse --port 8000 # HTTP mode
python server.py --decks-dir ~/Dropbox/my-decks # Custom deck location
```
Default transport is stdio. Default deck directory is `~/.config/scryfall-mcp/decks/`.
Default card cache is `~/.config/scryfall-mcp/cache/`.
---
## License
MIT. Scryfall data belongs to Scryfall LLC. Magic: The Gathering belongs to Wizards of the Coast.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues