使用说明
MTG Commander MCP Server
A Model Context Protocol (MCP) server for Magic: The Gathering Commander format, providing comprehensive card information, rulings, pricing, deck validation tools, and multi-platform deck importing.
Features
Tools (AI-Callable Functions)
Scryfall Card Data (8 tools)
-
search_cards – Search for MTG cards using Scryfall search syntax
- Supports advanced queries (colors, types, abilities, etc.)
- Returns up to 50 results with full card details
- Includes Commander legality status
-
get_card_details – Get detailed information about a specific card
- Oracle text and rules
- Mana cost, type, power/toughness
- Color identity
- Format legalities across all formats
- Artist and set information
-
check_commander_legality – Check if a card is legal in Commander
- Shows legality status across all formats
- Clear indication of banned/legal/not legal status
- Quick format validation
-
get_card_rulings – Get official card rulings and clarifications
- Official WotC rulings
- Dates and sources for each ruling
- Comprehensive rules clarifications
-
get_card_price – Get current card pricing
- USD and EUR prices from Scryfall
- BRL (Brazilian Real) pricing via real-time currency conversion
- Supports both regular and foil versions
- Optional set-specific pricing
-
get_banned_list – Get the current Commander banned list
- Real-time data from Scryfall
- 85+ banned cards (updated automatically)
- Complete list with card names
-
validate_deck – Validate a Commander deck
- 100-card deck size check
- Commander eligibility (rule 903.3) and ban check
- Singleton rule, exempting basic lands (including Snow-Covered) and cards like Relentless Rats
- Every card checked against the commander's color identity and the Commander banned list
- Flags names Scryfall does not recognize
- Looks cards up in batches of 75, so a full deck costs two Scryfall requests
- Supports JSON array or text format decklists
-
get_card_image – Get a card's image, localized by language
- Language-specific printing with English fallback
- Selectable size (small, normal, large, png, art_crop, border_crop)
- Renders inline in MCP Apps hosts via a
ui://mtg-cardwidget - Text summary with a Scryfall link as a fallback
Moxfield Integration (3 tools)
-
get_moxfield_deck – Fetch the complete deck from Moxfield
- Accepts deck URL or public ID
- Full decklist with card types organized
- Deck metadata (views, likes, comments, author)
- Commanders, mainboard, sideboard, maybeboard
- Last updated timestamp
-
get_moxfield_user_decks – Get user's deck list from Moxfield
- List all decks for a Moxfield user
- Paginated results (up to 100 per page)
- Deck summaries with views and likes
- Format and public URL for each deck
-
search_moxfield_decks – Search for decks on Moxfield by commander
- Required
commanderparameter (card name) - Optional
format(defaultcommander) - Optional
sort(updated,created,views,likes,comments,relevance; defaultviews) andsort_direction(asc/desc; defaultdesc) - Pagination via
limit(verified decks per page; default 10, max 20 — the per-call verification budget) andpage, the 1-based page of candidate decks searched: Moxfield cannot filter by commander, so a page may verify no decks while a later page verifies many - Returns deck metadata with views, likes, and URLs
- Moxfield's API cannot filter by commander, so results are verified per deck: candidates come from a card-name search and each one is fetched to confirm its commander zone (max 20 checks per call)
- Verification stops as soon as
limitdecks are confirmed, so the remaining candidates on that page are never examined and paging skips them — the next page resumes after the whole candidate page. The output states how many candidates were left unexamined - Output reports how many candidates were checked, how many could not be fetched, and flags incomplete verification when a deck read fails, the 30 s verification budget expires, or Moxfield rate-limits the run
- Moxfield reports
totalResultsas a saturated10000for any broad card-name search, so the output shows it as10000+ card-name matches — upstream cap, real total unknowninstead of echoing a fabricated count and page depth
- Required
Archidekt Integration (3 tools)
-
get_archidekt_deck – Fetch a complete deck from Archidekt
- Accepts deck URL or numeric ID (e.g.,
https://archidekt.com/decks/12345or12345) - Full decklist organised by a card type
- Commander(s) identified via the premier category flag
- Deck metadata (format, owner, views, EDH bracket, last updated)
- Direct link back to the Archidekt deck page
- Optional
lands_onlyflag — returns only land cards, ideal for landbase comparisons without the token overhead of a full decklist
- Accepts deck URL or numeric ID (e.g.,
-
get_archidekt_user_decks – Get a user's public decks from Archidekt
- List all public decks for any Archidekt username
- Paginated results with direct deck URLs
- Format name, view count, and last-updated date for each deck
-
search_archidekt_decks – Search public Commander decks by commander name
- Required
commanderparameter (card name, e.g."Atraxa, Praetors' Voice") - Optional
bracketfilter (1–4; omit to search all brackets) - Optional
sort(views,updated,created,price,size; defaultviews) andsort_direction(asc/desc; defaultdesc) - Optional filters:
colors(e.g.WU),deck_size(exact card count),author(Archidekt username),name(deck-name substring) - Pagination via
page(1-based, max 1000 — Archidekt's count saturates at 1000, so nothing is reachable beyond it) andlimit(default 10, max 60) - Invalid sort or out-of-range values return an explicit error instead of a silent fallback
- Each result includes deck name, author, view count, EDH bracket, last updated, and direct URL
- Required
Comprehensive Rules (3 tools)
-
get_rule - Get a specific Comprehensive Rule by number (e.g.
702.19), including its subrules. -
search_rules - Search the Comprehensive Rules text by keyword (default 10 results, max 20).
-
get_glossary_term - Get a Comprehensive Rules glossary definition by term.
EDHREC Meta Data (3 tools)
-
get_edhrec_recommendations – Get EDHREC recommendations for a commander
- High-synergy cards with synergy scores
- Most popular cards by inclusion rate
- New cards trending for the commander
- Card categories (creatures, instants, artifacts, etc.)
- Deck count and meta-statistics
- Salt scores for controversial cards
- Optional
theme(an EDHREC theme slug such asinfect; the unfiltered response lists them) - Optional
price_tier(budgetorexpensive)
-
get_edhrec_combos – Get popular combos for color combinations
- Combo cards and prerequisites
- Combo results (e.g., "Infinite mana", "Win the game")
- Usage statistics and percentages
- Ranked by popularity
- Colors as WUBRG letters in any order (
wu,UW,cfor colorless) or EDHREC names (azorius,esper)
-
get_edhrec_set_cards – Get the Commander-relevant cards of a Magic set
- New commanders the set introduced, with their deck counts
- The set's cards with the share of eligible decks playing them
- Takes the short lowercase set code (
blb,c21); full set names are not accepted
Resources (Data Sources)
-
commander://rules – Complete Commander format rules
- Deck construction guidelines
- Gameplay rules
- Winning conditions
- Official sources
-
commander://banned-list - JSON-formatted banned list
- Real-time data
- Card names, types, and mana costs
- Total count of banned cards
-
rules://comprehensive - Full official Magic: The Gathering Comprehensive Rules (fetched from WotC, large)
- Fetched at runtime from the official WotC page
- Cached for repeated use
- Includes all rules sections and glossary
-
ui://mtg-card - Card image widget for MCP Apps hosts
- Linked from the
get_card_imagetool, so supporting hosts render the card inline - The tool also returns the image itself and its URL for hosts without MCP Apps support
- Linked from the
Installation
Prerequisites
- Go 1.27.3 or later
- Internet connection (for Scryfall API and currency conversion)
Building from Source
# Clone or navigate to the project directory
cd mtg-mcp
# Install dependencies
go mod tidy
# Build the MCP server
go build -o mtg-mcp ./cmd/mtg-mcp
The compiled binary mtg-mcp is an MCP server for use with Claude Desktop or other MCP clients.
Usage
Running as an MCP Server
The server uses stdio transport for communication with MCP clients like Claude Desktop:
./mtg-mcp
Command-line flags:
| Flag | Description |
|---|---|
--version |
Print the version and exit |
--debug |
Enable debug logging |
--log-file PATH |
Write the log file to PATH (also settable with the MTG_MCP_LOG_FILE env var) |
Logs go to stderr and to a log file; stdout is reserved for the MCP protocol.
By default the log file is mtg-mcp/mtg-commander-server.log in the user cache directory.
That is ~/Library/Caches on macOS, ~/.cache on Linux and %LocalAppData% on Windows.
If the file cannot be opened, the server logs to stderr only and keeps running.
Connecting to Claude Desktop
To use this server with Claude Desktop, add the following configuration to your claude_desktop_config.json:
Location:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Configuration:
{
"mcpServers": {
"mtg-commander": {
"command": "/absolute/path/to/mtg-mcp/mtg-mcp"
}
}
}
Replace /absolute/path/to/mtg-mcp/ with the actual path to the binary.
After adding the configuration, restart Claude Desktop.
Connecting to Claude Code (Global Configuration)
To make this server available globally in Claude Code across all projects:
Option 1: Using the CLI (Recommended)
claude mcp add --transport stdio mtg-commander /absolute/path/to/mtg-mcp/mtg-mcp --scope user
Option 2: Manual Configuration
Edit the global MCP configuration file:
File location:
- macOS:
~/.claude/servers.json - Windows:
%APPDATA%\ClaudeCode\servers.json - Linux:
~/.config/ClaudeCode/servers.json
Configuration:
{
"mcpServers": {
"mtg-commander": {
"command": "/absolute/path/to/mtg-mcp/mtg-mcp",
"args": [],
"transport": "stdio"
}
}
}
Verify installation:
claude mcp list
You should see mtg-commander in the list of available servers.
Running with Docker (optional)
Docker is entirely optional — everything above (build from source, run
./mtg-mcp) keeps working unchanged. The container just saves you from
recompiling the binary on each machine.
Build the image (no local Go toolchain required):
make docker-build # builds mtg-mcp:latest (tiny distroless, stdio)
Register the image with an MCP client instead of a local binary path:
{
"mcpServers": {
"mtg-commander": {
"command": "docker",
"args": ["run", "-i", "--rm", "mtg-mcp:latest"],
"transport": "stdio"
}
}
}
Or via the CLI:
claude mcp add --transport stdio mtg-commander -- docker run -i --rm mtg-mcp:latest
Remote connector over HTTP. To expose the server as a Streamable HTTP
endpoint (e.g. for the claude.ai remote connector), run the mcp-proxy service
with Compose:
make docker-proxy # or: docker compose up --build
This publishes the endpoint on http://localhost:8080/mcp (override the port
with MTG_MCP_PORT). The proxy runs in stateful mode, which multi-step tool
flows require.
Example Queries
Once connected to Claude Desktop, you can ask questions like:
Card Data:
- "Search for blue counterspells in Commander"
- "Is Mana Crypt legal in Commander?"
- "What are the official rulings for Doubling Season?"
- "How much does Sol Ring cost in BRL?"
- "Show me the current Commander banned list"
- "Validate my Commander deck with Atraxa as commander"
Moxfield:
- "Fetch this Moxfield deck: https://www.moxfield.com/decks/abc123"
- "Show me decks by user JohnDoe on Moxfield"
- "What's in the mainboard of Moxfield deck xyz789?"
- "Search Moxfield for top Atraxa, Praetors' Voice decks"
- "Find the most popular Thrasios decks on Moxfield sorted by views"
Archidekt:
- "Fetch this Archidekt deck: https://archidekt.com/decks/12345"
- "Show me decks by user NorwegianWhaler on Archidekt"
- "What's the commander and decklist for Archidekt deck 67890?"
EDHREC:
- "What are the best cards for Atraxa, Praetors' Voice, according to EDHREC?"
- "Show me popular combos in Dimir colors (ub)"
- "What are high-synergy cards for Meren of Clan Nel Toth?"
- "Get me the top 5-color combos for WUBRG"
Architecture
Technology Stack
- Language: Go 1.27+
- MCP Framework: mark3labs/mcp-go
- Card Data API: Scryfall API via go-scryfall
- Currency Conversion: Frankfurter API (free, no API key)
- Logging: zerolog for structured JSON logging
- Transport: stdio (Model Context Protocol)
Data Sources
-
Card Data: Scryfall API
- Updated daily
- Complete MTG card database
- Includes rulings, legalities, and pricing
- Rate-limited to 10 requests/second (built into a client)
-
Commander Rules: Official format rules embedded in server
- Source: https://mtgcommander.net
- Format managed by Wizards of the Coast
-
Pricing:
- Base prices: Scryfall (USD/EUR)
- BRL conversion: Real-time exchange rates via Frankfurter API
- Note: Prices are indicative and may not reflect Brazilian market conditions
-
Moxfield: Unofficial API (https://api.moxfield.com)
- Deck data and user profiles
- Metadata including views, likes, comments
- Search endpoint lives on a different host (
api2.moxfield.com) than deck reads - Rate limit observed at roughly 11 rapid requests; commander verification is spaced and capped
- Note: No official public API; be respectful of rate limits
- Contact support@moxfield.com for authorized access
-
Archidekt: Open public API (https://archidekt.com/api)
- Deck data including full card lists and categories
- Owner, format, EDH bracket, and view count metadata
- Note: API is open for read access; credit deck creators when publishing data
- No API key required
-
EDHREC: Unofficial JSON endpoints (https://json.edhrec.com)
- Card recommendations and synergies
- Meta-statistics and popularity data
- Combo database
- Rate limit: Recommend 1 request/second
- Cached data (may not be real-time)
Project Structure
cmd/mtg-mcpholds the binary's entrypoint.internal/holds one package per upstream API, plusmtgserver, which exposes them as MCP tools and resources.- Each package keeps its tests next to the code: unit tests use
httptestmocks. - E2E tests (
e2e_test.go,*_e2e_test.go) call the real APIs and only build with thee2etag.
mtg-mcp/
├── cmd/
│ └── mtg-mcp/
│ └── main.go # Entrypoint: flags, logger, stdio transport
├── internal/
│ ├── mtgserver/ # MCP server: tool/resource registration and handlers
│ │ ├── server.go # Server type, tool and resource registration
│ │ ├── toolargs.go # Typed accessors for MCP tool arguments
│ │ ├── resources.go # Resource handlers (Commander rules, banned list)
│ │ ├── scryfall_handlers.go # Scryfall tools (search, details, price, image, …)
│ │ ├── moxfield_handlers.go # Moxfield tools
│ │ ├── archidekt_handlers.go # Archidekt tools
│ │ ├── edhrec_handlers.go # EDHREC tools
│ │ └── rules_handlers.go # Comprehensive Rules tools
│ ├── moxfield/ # Moxfield API client, commander verification, deck formatting
│ ├── archidekt/ # Archidekt API client, deck search, deck formatting
│ ├── edhrec/ # EDHREC JSON pages client and formatting
│ ├── rules/ # Comprehensive Rules fetcher, parser and cache
│ ├── deckfmt/ # Decklist grouping shared by the Moxfield and Archidekt formatters
│ ├── httpx/ # Shared HTTP GET/JSON helpers with timeouts and status errors
│ └── logging/ # zerolog setup (stderr + log file, never stdout)
├── docker/Dockerfile # stdio and mcp-proxy images
├── .github/workflows/ # CI, E2E, CD and lint workflows
├── Makefile # Build, test, lint and Docker targets
├── go.mod / go.sum # Go module dependencies
└── README.md # This file
Development
Quick Start with Makefile
The project includes a Makefile with common development tasks (compatible with macOS and Linux):
# View all available commands
make help
# Run all checks (format, lint, unit tests)
make check
# Build the binary
make build
# Run unit tests (fast)
make test-unit
# Run all tests including E2E
make test
# Run tests with coverage report
make test-coverage
# Format and lint code
make fmt lint
# Run CI pipeline locally
make ci
Common Makefile Commands:
| Command | Description |
|---|---|
make help |
Show all available commands |
make build |
Build the binary |
make test-unit |
Run unit tests only (fast, skips E2E) |
make test-e2e |
Run E2E tests only |
make test |
Run all tests (unit + E2E) |
make test-coverage |
Generate HTML coverage report |
make test-coverage-cli |
Show coverage in terminal |
make update-coverage-badge |
Update coverage badge in README with proper colors |
make bench |
Run benchmarks |
make fmt |
Format Go code |
make lint |
Run all linters |
make check |
Run fmt + lint + test-unit |
make ci |
Run full CI pipeline locally |
make clean |
Clean build artifacts |
make deps |
Download dependencies |
make tidy |
Tidy go.mod |
make docker-build |
Build the stdio (distroless) Docker image |
make docker-run |
Smoke-test the stdio image (--version) |
make docker-proxy |
Run the mcp-proxy HTTP service via Compose |
Running Tests
The project includes comprehensive unit tests with good coverage:
# Run unit tests (E2E tests are excluded unless the e2e build tag is set)
go test -v ./...
# Run tests with coverage
go test -v -coverprofile=coverage.out -covermode=atomic ./...
# View coverage report
go tool cover -html=coverage.out
# Show the server's log output while debugging a test (silenced by default)
MTG_MCP_TEST_LOGS=1 go test -v -run TestHandleValidateDeck ./internal/mtgserver/
End-to-End (E2E) Tests
E2E tests validate the integration with real external APIs (Scryfall, EDHREC, Moxfield, Archidekt, WotC rules).
They sit behind the e2e build tag, so go test ./... never calls the real APIs. Run them now and then, not on
every change, to avoid hammering the upstream services. They test:
- Real API connectivity and response formats
- Data structure validation with actual API responses
- Card name sanitization with real EDHREC endpoints
- Moxfield deck fetching and search
- Scryfall card queries and pricing
Running E2E Tests Locally:
# Run all tests including E2E
go test -tags e2e -v -timeout 5m ./...
# Run only E2E tests (same as make test-e2e)
go test -tags e2e -v -run E2E -timeout 5m ./...
Running E2E Tests via GitHub Actions:
E2E tests can be triggered manually through the GitHub Actions workflow:
- Go to the "Actions" tab in the repository
- Select "E2E Tests & Coverage" workflow
- Click "Run workflow"
- View test results, coverage, and logs
The workflow:
- Runs unit tests first for quick validation
- Runs all tests including E2E (with
-tags e2e) - Generates coverage badge and auto-commits to README
- Has a 15-minute timeout to accommodate API calls
- Uploads test logs as artifacts for debugging
- Only runs when manually triggered (not on push/PR)
E2E Test Files:
internal/archidekt/e2e_test.go- Archidekt API integration testsinternal/edhrec/e2e_test.go- EDHREC API integration testsinternal/moxfield/e2e_test.go- Moxfield API integration testsinternal/rules/e2e_test.go- Comprehensive Rules fetch integration testsinternal/httpx/json_v2_e2e_test.go- checksencoding/json/v2decodes real responses like v1internal/mtgserver/scryfall_e2e_test.goandscryfall_image_e2e_test.go- Scryfall API integration testsinternal/mtgserver/tools_e2e_test.go- calls every MCP tool and reads every resource against the live APIs (a test fails when a registered tool has no e2e case)
Note: E2E tests make real API calls and are subject to:
- API rate limits
- Network latency
- External API availability
- Potential API changes
Linting
The project uses golangci-lint for code quality checks:
# Run linter
golangci-lint run
# Run linter with auto-fix
golangci-lint run --fix
Adding New Tools
-
For a new upstream API, add a client package under
internal/(internal/edhrecis a small example). Give it aClientwith aBaseURLfield and aNewClient()for production, and hold it onServer. Fetch throughhttpx.GetJSON, which adds a request timeout, typed status errors andencoding/json/v2decoding. Unit tests point a&Client{BaseURL: server.URL}at anhttptestserver, so they never call the real API. -
Define the tool with
mcp.NewTool()ininternal/mtgserver/server.go. UseregisterTools()or the matching per-sourceregister*Tools()helper. -
Create a handler in the matching
internal/mtgserver/*_handlers.gofile, reading arguments with the helpers intoolargs.go:func (s *Server) handleToolName(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) -
Register it with
mcpServer.AddTool()and add its name to the expected list inserver_test.go. -
Write unit tests next to the code: client tests in the client package, handler tests in
internal/mtgserver.
Adding New Resources
-
Define the resource in
registerResources()ininternal/mtgserver/server.gousingmcp.NewResource() -
Create a handler function with a signature:
func (s *Server) handleResourceName(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) -
Register with
mcpServer.AddResource() -
Write unit tests for the resource handler
Continuous Integration
The project uses GitHub Actions with two main workflows:
CI Workflow (runs on push/PR):
- Build: Compiles the project for Linux/amd64
- Test: Runs unit tests (E2E tests are excluded by the
e2ebuild tag) - Lint: Runs golangci-lint for code quality checks
- Fast feedback loop for development (skips E2E tests)
E2E Tests & Coverage Workflow (manual trigger only):
- Unit Tests: Runs all unit tests first
- E2E Tests: Runs full test suite including real API calls to Scryfall, EDHREC, and Moxfield
- Coverage: Generates a coverage report from the full test suite
- Badge Generation: Updates README with current coverage percentage
- Auto-commit: Commits badge changes automatically
- Artifacts: Uploads test logs for debugging (7-day retention)
- Timeout: 15 minutes to accommodate external API calls
- Uses tj-actions/coverage-badge-go
- Thresholds: Green ≥80%, Yellow ≥60%, Red <60%
- Triggered via GitHub Actions UI → "E2E Tests & Coverage" → "Run workflow"
Limitations
-
Brazilian Pricing: Converted from USD using exchange rates. Does not account for:
- Import taxes and fees
- Brazilian market supply/demand
- Local marketplace pricing (LigaMagic, etc.)
-
Rate Limiting: Scryfall API has a 10 req/sec limit (automatically handled)
-
Deck Validation: Basic validation only. Full color identity and individual card legality checks require manual implementation for large decks.
Future Enhancements
Potential improvements:
- [x] Moxfield deck fetching and user deck lists
- [x] Moxfield deck search by commander
- [x] EDHREC card recommendations and combo database
- [x] Comprehensive unit tests with CI/CD
- [x] Archidekt deck fetching and user deck lists
- [ ] Direct LigaMagic integration for accurate BRL pricing
- [ ] Caching layer for frequently accessed cards
- [ ] Bulk deck validation with full color identity checking
- [ ] Card image retrieval
- [ ] Price history tracking
- [ ] Deck building suggestions based on EDHREC data
- [x] EDH bracket filtering and display for Archidekt decks
- [ ] Commander power level estimation (compute a bracket from a decklist)
Contributing
This is a personal project for Commander format assistance. Contributions, suggestions, and bug reports are welcome!
License
This project is provided as-is for personal use.
Note: This project uses data from Scryfall, which is provided under Wizards of the Coast's Fan Content Policy. Card data and imagery are property of Wizards of the Coast.
Acknowledgments
- Scryfall for comprehensive MTG card data
- Wizards of the Coast for Magic: The Gathering
- Anthropic for the Model Context Protocol
- The Commander Rules Committee and Commander Format Panel
Support
For issues or questions:
- Check Scryfall API status: https://scryfall.com/docs/api
- Verify MCP server is running: Check Claude Desktop logs
- Review configuration: Ensure a correct binary path (
mtg-mcp) inclaude_desktop_config.json