Skip to main content
Glama

R2-D2

A Star Wars Unlimited MCP server built with FastMCP. Search cards, build decks, validate formats, analyze the meta, and simulate two-player games — all through Claude Code, Claude Desktop, or any MCP-compatible client.

Card data comes from the live SWU DB API first and automatically falls back to the bundled local catalog when the API is unavailable.

Capabilities

Card Database

Tool

What it does

swu_search_cards

Natural text search with typed structured filters (aspect/type/arena/rarity/set as enums; cost/power/hp as {op, value} comparators). Returns a typed SearchResult.

swu_lookup_card

Exact lookup by name or set/number. Returns a typed CardDetail.

swu_random_card

Random card from a filtered pool. Returns a typed CardSummary.

swu_get_image

Front or back art URL for any card.

Typed search filters (v0.3.0)

swu_search_cards, swu_lookup_card, and swu_random_card now return Pydantic models instead of opaque dicts. FastMCP serializes them as both content (human-readable text) and structuredContent (typed JSON) — agents can read .cards[0].cost directly without parsing string keys.

Filters are typed too. Aspect/type/arena/rarity/set are Literal[...] enums, so the agent sees the valid options in the tool schema and typos like aspect="Cunninng" are rejected before the API call. Numeric stats use a structured {op, value} instead of magic strings:

swu_search_cards(
    query="Vader",
    filters={"aspect": "Villainy", "type": "Leader",
             "cost": {"op": ">=", "value": 5}},
)

Deck and game tools still return dict — that refactor is staged for a follow-up.

Deck Building

Tool

What it does

swu_upload_deck

Parse a decklist into a stateful session

swu_validate_deck

Check legality for Premier or Twin Suns (leaders, base, copy limits, aspect penalties)

swu_analyze_deck

Resource curve, aspect breakdown, synergy score, role analysis

swu_suggest_cards

Targeted card suggestions for a stated goal or matchup

swu_generate_deck

First-pass brew from a theme, leaders, and format

swu_export_deck

Export a session to a shareable decklist

Game Simulation

Tool

What it does

swu_start_game

Two-player setup with deck loading

swu_get_game_state

Current board state, hand, resources, damage

swu_get_legal_actions

Available actions with targeting options

swu_take_game_action

Execute an action (play, attack, pass, etc.)

swu_take_ai_turn

Let the AI pilot take a full turn

swu_draw_card / swu_view_hand / swu_view_board

Card management

swu_play_card / swu_move_card / swu_defeat_card / swu_set_card_state

Direct board manipulation

swu_mulligan / swu_resource_phase / swu_sideboard

Phase management

Related MCP server: lorcana-mcp

Quick Start

uv sync
uv run python scripts/start_stdio.py

Claude Code / Claude Desktop Config

Add to ~/.mcp.json:

{
  "mcpServers": {
    "r2-d2": {
      "command": "uv",
      "args": [
        "--directory",
        "/path/to/r2-d2",
        "run",
        "python",
        "scripts/start_stdio.py"
      ]
    }
  }
}

Offline Catalog

A bundled card catalog (data/catalog/cards.json) is auto-discovered at startup. The server uses it as a fallback whenever the live API is unavailable — no configuration needed.

To rebuild the catalog from the latest API data:

uv run python scripts/build_catalog.py

Environment Variables

All optional — sensible defaults are built in.

Variable

Default

Purpose

SWU_MCP_API_BASE_URL

https://api.swu-db.com

Live card data API

SWU_MCP_CARD_CATALOG_PATH

Auto-discovered from data/catalog/

Local JSON fallback

SWU_MCP_CACHE_DIR

.swu-mcp-cache

Per-card response cache

SWU_MCP_DEFAULT_LIMIT

10

Default search result limit

Format Support

Premier — 1 leader, 1 base, 50+ main deck (3x copy limit), 10-card sideboard, off-aspect penalty reporting.

Twin Suns — 2 leaders sharing Heroism or Villainy, 1 base, 80+ singleton main deck, no sideboard.

Game Engine

The simulator supports two-player games with:

  • Resource turns, unit/event play, leader deployment, combat, base damage

  • Stack/priority loop with targeting and responses

  • Ambush, Sentinel, Saboteur, Overwhelm, Shielded, Restore, Raid, Hidden

  • When Played / On Attack / When Defeated trigger patterns

  • Upgrade attachment with static buffs and keyword grants

  • Basic AI pilot for sparring

This is a pragmatic rules engine for playtesting and AI sparring, not a comprehensive rules simulator. Edge cases around complex upgrade conditions, nested optional triggers, and deep timing interactions are not fully covered.

Example Prompts

  • "Search for all Cunning leaders from Legends of the Force"

  • "Generate a Twin Suns deck with Cad Bane and Jabba the Hutt"

  • "Upload this decklist, analyze it, and suggest swaps for an aggro-heavy meta"

  • "Start a game with my Qui-Gon deck against a generated Villainy aggro deck"

  • "Take my action to play Boba Fett, then let the AI respond"

License

MIT

Available Tools

32 tools
swu_analyze_deckB

Analyze a Star Wars Unlimited deck's curve, aspects, roles, and synergy.

Inputs: decklist, session_id, format_name, meta_context, +1 more. Returns: object

swu_collection_combo_profileA

Profile the loaded collection for combo-package density. Returns per-package enabler/payoff counts (Force engine, Indirect damage, When Defeated, Pilot/Vehicle, Token swarm, Cost reduction, Fortress, Bounty Hunter, Mandalorian) and flags which are 'live' (≥4 enablers + ≥2 payoffs). Pass refresh=true to recompute from scratch.

Inputs: refresh. Returns: object

swu_collection_summaryA

Summarize the loaded Star Wars Unlimited collection — total cards, unique printings, per-set breakdown, and storage path.

Inputs: no named parameters. Returns: object

swu_defeat_cardA

Defeat a card from the board or another in-play zone and move it to discard.

Inputs: zone, card_name, session_id. Returns: object

swu_draw_cardB

Draw one or more cards from an uploaded deck session.

Inputs: count, session_id. Returns: object

swu_export_deckB

Export a deck session or decklist as plain text or JSON.

Inputs: decklist, session_id, format_name, export_format. Returns: object

swu_generate_deckA

Generate a first-pass Star Wars Unlimited brew around a theme. Set only_owned=True to build only with cards in your loaded collection (quantities will be capped by ownership). By default the deck is restricted to on-aspect cards (the aspects granted by the two leaders plus the base); set allow_off_aspect=True to permit off-aspect splashes that cost extra resources. Set target_avg_cost to steer the curve (e.g. 2.5 for an aggressive low-curve deck, 3.5 for midrange); lower = cheaper and faster. When omitted, the format default is used.

Inputs: theme (required), budget, base_name, only_owned, +7 more. Returns: object

swu_get_game_stateA

Get the current two-player game state, with hidden information filtered by viewer unless reveal_all is true.

Inputs: game_id (required), viewer, reveal_all. Returns: object

swu_get_imageA

Return the front or back image URL for a Star Wars Unlimited card.

Inputs: name, set_code, back_face, card_number. Returns: object

swu_list_collectionA

List owned printings from the loaded collection, optionally filtered by set_code. Pass limit=0 for no limit.

Inputs: limit, set_code. Returns: object

swu_load_collectionA

Import a Star Wars Unlimited card collection from a SWUDB CSV export (columns: Set, CardNumber, Count, IsFoil). Persists to disk. Set merge=True to add to existing collection instead of replacing it.

Inputs: csv_path (required), merge. Returns: object

swu_lookup_cardA

Look up a specific Star Wars Unlimited card by name or set_code+card_number. Returns the full CardDetail record.

Inputs: name, set_code, card_number. Returns: Full card record returned by swu_lookup_card.

swu_move_cardA

Move an existing in-play card or leader/resource between zones such as ground, space, resource, and discard.

Inputs: ready, card_name, session_id, destination, +1 more. Returns: object

swu_mulliganA

Take a full-hand mulligan in the current deck session.

Inputs: session_id. Returns: object

swu_owned_countA

Return how many copies of a specific Star Wars Unlimited printing the user owns. Use set_code and card_number (e.g. LOF 47).

Inputs: set_code (required), card_number (required). Returns: object

swu_play_cardB

Play or deploy a card from hand, discard, or leader zone into ground, space, or resources.

Inputs: ready, damage, shield, card_name, +4 more. Returns: object

swu_random_cardB

Return a random Star Wars Unlimited card from a search result set.

Inputs: query, filters. Returns: Lightweight card view returned in search results. Accepts either CardRecord.to_…

swu_rank_leader_pairsA

Twin Suns only — brew a deck for every legal leader pairing in your owned pool and rank them by composite score (synergy + interaction density - off-aspect burden). Use moral='Heroism' or 'Villainy' to narrow. primary_aspects filters leaders whose aspects intersect the given list. include_decks=true returns full holoscan lists for the top_k results. Useful for surfacing leader pairs you wouldn't have considered manually.

Inputs: moral, theme, top_k, base_name, +4 more. Returns: object

swu_resource_phaseA

Advance the resource phase by readying resources, optionally resourcing a hand card, and drawing for turn.

Inputs: session_id, draw_for_turn, resource_card. Returns: object

swu_search_cardsA

Search Star Wars Unlimited cards using natural text and optional structured filters. Pass query for free-text matching; use filters to constrain by aspect, type, arena, rarity, set, trait, or numeric stats (cost/power/hp). Returns a typed SearchResult.

Inputs: limit, order, query, filters, +1 more. Returns: Top-level search result envelope.

swu_set_card_stateC

Update a card's ready state and counters while it is in play.

Inputs: zone, ready, damage, shield, +3 more. Returns: object

swu_sideboardB

Swap cards between the main deck and sideboard, then reset playtest zones.

Inputs: swaps, session_id. Returns: object

swu_simulate_gameA

Run a full AI-vs-AI game simulation to completion. Both players must be AI (set player_is_ai=true in start_game). Returns winner, base damage breakdown, MVP cards, and full game log.

Inputs: game_id (required), max_turns. Returns: object

swu_start_gameC

Start a two-player Star Wars Unlimited game between you and Claude.

Inputs: game_id, format_name, player_name, meta_context, +8 more. Returns: object

swu_suggest_cardsA

Suggest cards to improve a Star Wars Unlimited deck toward a stated goal. Set only_owned=True to restrict suggestions to cards in your loaded collection.

Inputs: goal (required), limit, decklist, only_owned, +4 more. Returns: object

swu_take_ai_turnC

Let the AI pilot its side for one turn or until it ends the turn.

Inputs: game_id (required), player_id, max_actions. Returns: object

swu_take_game_actionC

Take a game action such as resource, play, resolve_effect, pass_priority, deploy_leader, attack, or end_turn.

Inputs: game_id (required), action, card_name, player_id, +5 more. Returns: object

swu_upload_deckC

Upload a Star Wars Unlimited decklist into a named stateful session.

Inputs: decklist (required), shuffle, session_id, format_name, +1 more. Returns: object

swu_validate_deckB

Validate a Star Wars Unlimited deck for Premier or Twin Suns.

Inputs: decklist, session_id, format_name. Returns: object

swu_view_boardB

View the current in-play board state, including ground, space, leaders, bases, and resources.

Inputs: session_id. Returns: object

swu_view_handA

View the current hand, resources, and core counters for a deck session.

Inputs: session_id. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 32 tools

    Disambiguation4/5

    Tools are largely distinct, each targeting a specific resource or action (search, lookup, collection, deck, game). Minor overlap exists between view_hand/view_board and get_game_state, and play_card vs take_game_action, but descriptions clarify the contexts.

    Naming Consistency4/5

    All tools share the swu_ prefix and use snake_case, with most following a verb_noun pattern. A few exceptions like owned_count and collection_summary deviate from verb-first but remain readable and predictable.

    Tool Count2/5

    32 tools is above the 25+ threshold that indicates a bloated surface. While the scope covers card data, collection, deckbuilding, and gameplay, the count feels heavy and could be consolidated (e.g., combining game actions into a single action dispatcher).

    Completeness4/5

    The tool set covers card search, collection management, deck analysis/generation, playtesting, and full game simulation thoroughly. Minor gaps exist (no direct single-card ownership update, no persistent deck save beyond export), but agents can work around them.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      B
      maintenance
      Unified MCP server for Magic: The Gathering, combining Scryfall card search and pricing, EDHRec commander recommendations, Archidekt deck reading, and decklist validation into a single service.
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      An MCP server that lets AI assistants look up Disney Lorcana TCG events, stores, and tournament data via the Ravensburger Play API.
      45 npm
      -