Skip to main content
Glama
Liaxum

piltover-archive

by Liaxum

PiltoverArchives-mcp

An MCP server for the Piltover Archive API — a community card database, deck builder and proxy generator for the Riftbound TCG.

It exposes card search, card lookup, set listing and decklists as MCP tools, so an assistant can answer questions about Riftbound cards it otherwise knows nothing about.

Why this exists

Riftbound is recent enough that its card data is not in any language model's training data. Ask an assistant what Vi, Destructive costs and you get a guess. This server closes that gap by giving it the real database.

Related MCP server: Scryfall MCP Server

Install

git clone https://github.com/Liaxum/PiltoverArchives-mcp.git
cd PiltoverArchives-mcp
npm install
npm run build

Claude Code

claude mcp add piltover-archive -- node /absolute/path/to/PiltoverArchives-mcp/dist/index.js

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "piltover-archive": {
      "command": "node",
      "args": ["/absolute/path/to/PiltoverArchives-mcp/dist/index.js"]
    }
  }
}

No credentials are needed. See Authentication — supplying an API key currently makes things worse, not better.

Tools

Tool

What it does

piltover_search_cards

Search cards by text, colour, type, set, rarity, tag, and energy/power/might ranges

piltover_get_cards

Resolve known cards in one request by collector number, exact name, or UUID

piltover_list_sets

List every set with its prefix and release date

piltover_search_decks

Search public decklists by name, description or legend

piltover_get_deck

Fetch one decklist, resolving card UUIDs into real card names

All tools are read-only and take a response_format of markdown (default) or json.

piltover_get_deck is the one that earns its keep: the API stores deck contents as bare UUIDs with no names attached, so the tool batch-resolves every one of them and renders a readable list.

## Main deck (39)
- 3x Charm [OGN-043] — Spell, 1 energy, Calm
- 3x B.F. Sword [SFD-161] — Gear, 4 energy, Order

Configuration

Variable

Default

Purpose

PILTOVER_API_BASE_URL

https://piltoverarchive.com/api/external/v1

Override the API base

PILTOVER_API_KEY

(unset)

Optional bearer token. Leave unset — see below

Development

npm run build     # compile TypeScript
npm run inspect   # run against the MCP Inspector

API reference

The rest of this document records what was learned about the upstream API. It is kept because none of it is officially documented anywhere.

How this was determined

Piltover Archive publishes no API documentation. There is no docs. or developers. host, no OpenAPI/Swagger document, no developer section on the site, and nothing indexed by search engines.

Everything below was reverse-engineered from the production Next.js client bundles (https://piltoverarchive.com/_next/static/chunks/*.js, notably the API client in module 491560) and then verified with live requests. Where something was inferred but not confirmed against the running API, it is marked as such.

Because none of this is a published contract, it may change without notice. Treat it as observed behaviour, not a stable interface.


Base URL

The API is not on a separate host. It is a route inside the main Next.js app:

https://piltoverarchive.com/api/external/v1

The client bundle reads a server-side EXTERNAL_API_URL environment variable and falls back to the relative path /api/external, which suggests the backend may also be reachable directly on another origin. That origin is not public; api.piltoverarchive.com does not resolve.

Infrastructure observed from response headers: Cloudflare in front of Railway (x-railway-edge: iad1), with Clerk for user authentication (x-clerk-auth-status).

Authentication

Bearer tokens only:

Authorization: Bearer <token>

An x-api-key header is not read — sending the key that way is treated as no credential at all.

Two kinds of bearer token exist. The web app sends a Clerk session token for signed-in users. Programmatic clients are expected to send an API key with an ak_ prefix.

Important: the read endpoints are public

/v1/cards, /v1/decks and /v1/sets return 200 with no credentials at all. A card-data MCP server needs no authentication to be useful.

The ak_ API key and partner status

An ak_-prefixed API key was tested against this API. The results are worth recording, because the failure mode is misleading:

Request

Response

Deliberately invalid ak_… token

401 INVALID_API_KEY — "Invalid API key"

The real ak_… key

401 PARTNER_REQUIRED — "Partner identification required"

The real key on /v1/partners

403 ADMIN_REQUIRED — "Admin access required"

The key is valid and recognised — it produces a different error than a forged one, and it passes the authentication gate on /v1/partners only to fail the authorization gate. What it lacks is an association with a partner record on the server side.

The practical consequence is that sending the key is currently worse than sending nothing:

Endpoint

No auth

With the ak_ key

GET /v1/cards

200

401 PARTNER_REQUIRED

GET /v1/decks

200

401 PARTNER_REQUIRED

GET /v1/sets

200

401 PARTNER_REQUIRED

GET /v1/notifications

401

401 PARTNER_REQUIRED

GET /v1/collection/stats

401

401 PARTNER_REQUIRED

Authenticating downgrades otherwise-public endpoints to 401 and unlocks nothing.

This is not a missing request header. X-Partner-Id, X-Partner and X-Partner-Key were each tried alongside the bearer token and all returned the identical PARTNER_REQUIRED. Partner association has to be granted server-side. The app has an internal /admin/partners route, a checkIsPartner server action and a usePartnerStatus hook, and exposes "Partner" as an account tier alongside admin and supporter — so this is an account flag the Piltover Archive maintainers set, reachable through their help channels (email or Discord).

Recommendation for this server: build against the public endpoints and do not send a key by default. Put the Authorization header behind an opt-in setting so it can be switched on if and when partner access is granted.

Response envelope

List endpoints return:

{
  "data": [ ... ],
  "pagination": {
    "total": 1238, "page": 1, "limit": 1,
    "totalPages": 1238, "hasNext": true, "hasPrevious": false
  },
  "meta": { "filters": { "colors": [ { "id": "…", "name": "Body", "count": 223 } ] } }
}

meta.filters carries facet counts for the current result set, which is handy for exposing filter options without a second request.

Errors are JSON: {"error": "CODE", "message": "…"}. Some responses also carry a requestId. Validation failures use a different shape: {"type":"validation","on":"params","found":{…}} with status 422.

Observed error codes: INVALID_API_KEY, AUTH_REQUIRED, PARTNER_REQUIRED, ADMIN_REQUIRED, INVALID_REQUEST, PREMIUM_REQUIRED, NOT_FOUND.

Endpoints

Cards

GET  /v1/cards               # search — public
POST /v1/cards/batch         # bulk lookup — public

/v1/cards/batch accepts at least one of variantNumbers, names or ids:

curl -X POST https://piltoverarchive.com/api/external/v1/cards/batch \
  -H 'Content-Type: application/json' \
  -d '{"variantNumbers":["ARC-001"]}'

Search parameters, taken from the client's own parameter normaliser (urlToCardSearchParams) and confirmed working:

Kind

Parameters

Notes

Free text

q, name, description, artist, flavor

trimmed, truncated to 200 chars

Identity

id

truncated to 64 chars

Multi-value

colors, sets, types, supertypes, variants, excludeVariants, rarities, tags, artworks, releaseDateAfter

comma-separated, truncated to 500 chars

Ranges

energyMin/energyMax, powerMin/powerMax, mightMin/mightMax, qtyMin/qtyMax

non-negative integers

Sorting

sortBy, or sort + dir (asc|desc)

sortBy takes precedence

Paging

page (≥1), limit (≥1, capped at 100)

Convenience

new=true

client-side sugar that sets releaseDateAfter to a "new card" cutoff

Example — ?q=Vi&limit=2&sort=name&dir=asc returns 56 matches; ?energyMin=5 returns 313.

A card variant looks like:

{
  "id": "a60d2063-…", "variantNumber": "ARC-001",
  "rarity": "Showcase", "variantType": "Promo", "foilMode": "foil_only",
  "imageUrl": "https://piltoverarchive.b-cdn.net/…webp",
  "artist": "Fortiche Production", "releaseDate": "2025-10-14",
  "variantLabel": "Arcane Box Promo",
  "showInLibrary": true, "isCollectible": true,
  "cardmarketId": 858987, "tcgplayerId": 678053,
  "cardmarketPrice": 94.35, "tcgplayerPrice": 97.16,
  "set":  { "id": "…", "name": "Arcane Box Set", "prefix": "ARC", "releaseDate": "2025-12-31" },
  "card": {
    "id": "…", "name": "Vi, Destructive",
    "types": ["Unit"], "type": "Unit", "super": "Champion",
    "description": "[GANKING] …", "energy": 2, "might": 3, "power": 1,
    "tags": ["Vi", "Piltover"], "maxCopies": null, "banEffectiveDate": null,
    "colors": [ { "id": "…", "name": "Fury", "hexCode": "#CB222D", "imageUrl": "…" } ]
  }
}

Note the card/variant split: a card is the game object, and the top level is a printing of it. Market prices come from Cardmarket and TCGplayer.

Sets

GET /v1/sets                 # public

Returns { id, name, prefix, releaseDate, imageUrl }, e.g. Origins | Nexus Night (OGN-NN).

Decks

GET    /v1/decks             # list — public
GET    /v1/decks/{uuid}      # detail
PATCH  /v1/decks/{uuid}
DELETE /v1/decks/{uuid}
GET    /v1/decks/{uuid}/likes
POST   /v1/decks/{uuid}/like
DELETE /v1/decks/{uuid}/like

{uuid} must be a UUID — /v1/decks/me returns 422.

Deck list parameters differ from card search in two ways worth knowing:

  • The request parameter is limit, but the response reports it back as pageSize. Sending pageSize is ignored and you silently get the default 20.

  • q searches deck name, description and legend name, so a champion name finds decks led by that champion even when the title never mentions it.

  • sort + dir order the results; sortBy is ignored here (unlike card search).

  • total appears to cap at 10000.

Deck contents are stored as bare identifiers — {cardId, variantId, quantity} — with no card names. Sections are champions, battlefields, runes, maindeck, sideboard and bench. To render a decklist you must collect the ids and resolve them through POST /v1/cards/batch with ids.

Deck export

All POST, all taking a deckCode plus an options object. image and proxies return a binary blob rather than JSON; text returns { "text": … }.

POST /v1/decks/export/image           # deck image (PNG)
POST /v1/decks/export/proxies         # printable proxy PDF
POST /v1/decks/export/registration    # tournament registration sheet
POST /v1/decks/export/tts             # Tabletop Simulator
POST /v1/decks/export/text            # plain text list

Export options seen in the client include expandCards, showQR, showWatermark, sortBy (as {field, order} pairs) and per-section toggles (legend, battlefields, runes). Some option combinations return PREMIUM_REQUIRED. Only the image export passes a bearer token.

Authenticated / restricted

Reachable but gated; not usable without partner or admin status:

GET    /v1/notifications                       # AUTH_REQUIRED
GET    /v1/collection/stats                    # AUTH_REQUIRED
GET    /v1/collection/export
GET    /v1/collection/sets/{id}/details
GET    /v1/collection/users/{id}/ownership
PATCH  /v1/collection/{id}
PATCH  /v1/collection/binders/{id}
DELETE /v1/collection/{id}
DELETE /v1/collection/binders/{id}
GET    /v1/partners/{id}
GET    /v1/partners                            # ADMIN_REQUIRED
PATCH  /v1/admin/decks/{id}/featured           # admin only

/v1/users and /v1/news return a bare 403 {"error":"Forbidden"}. /v1/tournaments returns NOT_FOUND, despite tournaments existing in the product — that data is presumably served another way.

Implementation status

The tools listed at the top of this document are implemented and verified against the live API. All of them use unauthenticated endpoints.

Collection and notification tools are not implemented: they require partner access that the current key does not have. They can be added once Piltover Archive grants it, without changing anything already built.

Caveats

  • None of this is a published API. It can change at any time, without notice.

  • Be a good citizen: the endpoints are public but not advertised as such. Cache responses, respect the limit cap of 100, and do not hammer the service.

  • Card data and images are Riot Games intellectual property, served by a community project. This repository is unaffiliated with both.

Available Tools

5 tools
piltover_get_cardsLook up Riftbound cards by identifierA
Read-onlyIdempotent

Resolve known Riftbound cards in one request, by collector number, exact name, or UUID.

Provide at least one of variantNumbers, names or ids; they can be combined. This is the right tool for turning the cardId/variantId values inside a deck into real card names, and for looking up a list of cards without one search per card.

Args:

  • variantNumbers: collector numbers, e.g. ["OGN-007"]

  • names: exact card names, e.g. ["Vi, Destructive"]

  • ids: card or variant UUIDs

  • response_format: 'markdown' (default) or 'json'

Examples:

  • "What is OGN-007?" -> { variantNumbers: ["OGN-007"] }

  • Resolving a decklist -> { ids: ["0283d70f-…", "f40b0e74-…"] }

  • Don't use when: you are searching by criteria rather than identity — use piltover_search_cards.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsNoCard or variant UUIDs, as returned in deck contents.
namesNoExact card names, e.g. ["Vi, Destructive"].
variantNumbersNoCollector numbers, e.g. ["OGN-007", "ARC-001"].
response_formatNomarkdown for reading, json for further processing.markdown

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description still adds real behavioral value by stating the cross-parameter constraint ('provide at least one of') that the schema's zero required fields does not enforce, plus the batch-vs-single-search intent and the response_format choice.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, then the constraint, then args and mini-examples; every section is useful. The Args block partially restates the schema descriptions, which is mild redundancy but it is paired with mapping examples that add value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an identity-lookup tool with no output schema, the description covers purpose, inputs, combination rules, alternatives and response_format. It does not describe the shape of returned card data, a minor gap, but the response_format hint and 'turn ids into real card names' framing give the agent enough to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description goes beyond it with concrete example values (["OGN-007"], ["Vi, Destructive"]) and semantic framing such as 'card or variant UUIDs, as returned in deck contents', clarifying where the ids come from.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (resolve/look up) plus resource (Riftbound cards) with three explicit lookup keys (collector number, exact name, UUID), and it names the sibling it is not (search_cards). An agent can distinguish it from piltover_search_cards without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the selection condition ('Provide at least one of variantNumbers, names or ids'), the concrete use cases (resolving cardId/variantId from a decklist, batch lookup to avoid one search per card), and an explicit negative case routing to piltover_search_cards for criteria-based search.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

piltover_get_deckGet a Riftbound decklistA
Read-onlyIdempotent

Fetch one deck by ID and return its full contents.

The API stores deck contents as bare card UUIDs, so by default this tool resolves every one of them into card names, types, costs and colours — that resolution is the point of the tool, and it costs a few extra requests. Set resolve_cards=false for the raw id form.

Sections returned: champions, battlefields, runes, main deck, sideboard, bench.

Args:

  • deck_id: the deck UUID, as returned by piltover_search_decks

  • resolve_cards: resolve card UUIDs to names (default true)

  • response_format: 'markdown' (default) or 'json'

Examples:

  • "What's in deck ae198cdf-…?" -> { deck_id: "ae198cdf-…" }

  • Don't use when: you only need deck metadata for many decks — piltover_search_decks already returns that.

ParametersJSON Schema
NameRequiredDescriptionDefault
deck_idYesDeck UUID, from piltover_search_decks.
resolve_cardsNoResolve card UUIDs into card names and stats.
response_formatNomarkdown for reading, json for further processing.markdown

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds genuinely useful behavior the annotations cannot express: card UUIDs are resolved by default at the cost of extra requests, and the exact sections returned (champions, battlefields, runes, main deck, sideboard, bench). It stops short of describing output format details, but that is minor here.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and behavior, then a scannable example and exclusion. The 'Args' block largely duplicates the schema descriptions, which is redundant given 100% coverage, but the overall length is proportionate to a 3-parameter tool with a non-obvious default.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, yet the description enumerates the returned sections and the markdown/json format choice, so an agent knows what comes back. Combined with the worked example and the explicit routing rule, nothing needed to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: resolve_cards is explained as the tool's purpose with a stated cost tradeoff and a false-escape hatch, response_format is framed as reading vs. further processing, and deck_id's origin is tied to piltover_search_decks. This goes beyond the schema text rather than restating it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Starts with a specific verb+resource+scope: fetch one deck by ID and return its full contents. It also names the sibling piltover_search_decks as the source of the deck_id and clarifies the resolution behavior that is 'the point of the tool', so an agent can distinguish it from the search tool without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Contains an explicit exclusion — 'Don't use when: you only need deck metadata for many decks — piltover_search_decks already returns that' — and states the condition under which the costly default (resolve_cards=true) should be switched off. Both when-to-use and when-not-to-use are covered with the alternative named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

piltover_list_setsList Riftbound setsA
Read-onlyIdempotent

List every Riftbound card set, with its prefix and release date.

Set prefixes (e.g. OGN, ARC) are what the sets filter of piltover_search_cards expects, so call this first when a question names a set in words ("the Arcane box") rather than by prefix.

Args:

  • response_format: 'markdown' (default) or 'json'

Examples:

  • "What Riftbound sets exist?" -> {}

  • "What's the prefix for Origins?" -> {} then read the table

ParametersJSON Schema
NameRequiredDescriptionDefault
response_formatNomarkdown for reading, json for further processing.markdown

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description adds genuine behavioral context beyond that: the shape of the returned data (prefix + release date) and the response_format tradeoff for downstream processing. It does not mention pagination or ordering, so it isn't fully exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose, then adds the cross-tool rationale, args, and short examples. Every block earns its place and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-optional-param, no-output-schema tool, the description supplies what the return contains (prefix, release date), the routing rationale, and the format options. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and there is only one enum-constrained parameter, so the schema already documents response_format. The description restates the 'markdown (default) or json' options without adding format-specific meaning beyond the existing enum description — baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('List every Riftbound card set') and specifies the returned fields (prefix and release date). It also differentiates itself from the sibling piltover_search_cards by explaining that its prefixes feed that tool's `sets` filter.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger condition: call this first when a question names a set in words rather than by prefix. The worked examples ('What's the prefix for Origins?' -> {} then read the table) reinforce exactly when and how to invoke it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

piltover_search_cardsSearch Riftbound cardsA
Read-onlyIdempotent

Search the Piltover Archive database of Riftbound trading card game cards.

Riftbound is a Riot Games TCG whose card data is not part of any model's training data, so use this tool rather than answering from memory whenever a specific card, cost, rules text or price is involved.

Filters combine with AND. Every filter is optional; with none, it lists all cards. Results are card printings (variants), each carrying the game card under card.

Args:

  • q: free-text across name, rules text, flavour and artist

  • name / description / artist / flavor: search one field only

  • colors / sets / types / supertypes / rarities / tags: multi-value filters

  • energyMin|Max, powerMin|Max, mightMin|Max: numeric ranges

  • releaseDateAfter: ISO date lower bound

  • sort + dir: ordering; page + limit: pagination (limit max 100)

  • response_format: 'markdown' (default) or 'json'

Examples:

  • "What does Vi, Destructive do?" -> { name: "Vi, Destructive" }

  • "Cheap Fury units" -> { colors: ["Fury"], types: ["Unit"], energyMax: 2 }

  • "Most expensive Showcase cards" -> { rarities: ["Showcase"], sort: "cardmarketPrice", dir: "desc" }

  • Don't use when: you already have exact collector numbers or IDs — use piltover_get_cards, which is one request instead of many.

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoFree-text search across card name, rules text, flavour text and artist.
dirNoSort direction. Requires `sort`.
nameNoMatch against the card name only.
pageNo1-based page number.
setsNoSet prefixes or IDs, e.g. OGN, ARC. Accepts a list or a comma-separated string.
sortNoField to sort by, e.g. name, releaseDate, energy.
tagsNoTags, which cover champions and regions, e.g. Vi, Piltover. Accepts a list or a comma-separated string.
limitNoResults per page (max 100).
typesNoCard types, e.g. Unit, Spell, Rune, Battlefield, Legend. Accepts a list or a comma-separated string.
artistNoMatch against the artist name.
colorsNoColour names, e.g. Fury, Calm, Body, Mind, Chaos, Order. Accepts a list or a comma-separated string.
flavorNoMatch against the flavour text.
mightMaxNoMaximum might.
mightMinNoMinimum might.
powerMaxNoMaximum power.
powerMinNoMinimum power.
raritiesNoRarities, e.g. Common, Rare, Epic, Showcase. Accepts a list or a comma-separated string.
variantsNoVariant types to include, e.g. Promo. Accepts a list or a comma-separated string.
energyMaxNoMaximum energy cost.
energyMinNoMinimum energy cost.
supertypesNoSupertypes, e.g. Champion, Signature. Accepts a list or a comma-separated string.
descriptionNoMatch against the rules text only.
excludeVariantsNoVariant types to exclude. Accepts a list or a comma-separated string.
response_formatNomarkdown for reading, json for further processing.markdown
releaseDateAfterNoOnly cards released on or after this ISO date (YYYY-MM-DD).

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/openWorld/non-destructive, so the safety profile is covered. The description adds genuinely new behavior: filters combine with AND, every filter is optional so an empty call lists all cards, and results are printings rather than game cards, with the underlying card nested under `card`. It does not mention pagination metadata or rate/latency behavior, so it stops short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose, then filters, then Args, then Examples, then the don't-use case. The Args block largely restates the schema, which is some duplication, but the example section is high-value and the whole thing stays scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 25-parameter tool with no output schema, the description covers result shape (printing + nested card), pagination limits, default response format, and failure mode routing to the sibling. Minor gap: no detail on what pagination/total metadata the response carries, but the essential call-correctness information is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description goes beyond it by grouping parameters into semantic families (free-text vs single-field, multi-value filters, numeric ranges, sort/dir, page/limit, response_format) and by tying natural-language questions to concrete parameter combinations in the examples, which the schema alone does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb and resource ('Search the Piltover Archive database of Riftbound trading card game cards') and immediately differentiates itself from the sibling piltover_get_cards, which handles exact IDs/collector numbers. The scope note that Riftbound data is absent from training data makes the tool's role unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use ('use this tool rather than answering from memory whenever a specific card, cost, rules text or price is involved') and explicit when-not-to-use with the named alternative ('you already have exact collector numbers or IDs — use piltover_get_cards, which is one request instead of many'). Both the trigger and the exclusion are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

piltover_search_decksSearch Riftbound decksA
Read-onlyIdempotent

Search public decklists published on Piltover Archive.

Useful for seeing how a champion or archetype is actually built, and what the community is playing right now.

Args:

  • q: free-text across deck name, description and legend name, so a champion name finds decks led by that champion even when the title never says it

  • sort: field to order by, e.g. likes, views, createdAt (pair with dir)

  • dir: 'asc' or 'desc'

  • page, limit: pagination (limit max 100)

  • response_format: 'markdown' (default) or 'json'

Examples:

  • "Popular Akali decks" -> { q: "Akali", sort: "likes", dir: "desc" }

  • "Newest decks" -> { sort: "createdAt", dir: "desc" }

Returns deck summaries including a deck ID; pass that to piltover_get_deck for the full card list.

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoFree-text search across deck name, description and legend name.
dirNoSort direction. Requires `sort`.
pageNo1-based page number.
sortNoField to sort by, e.g. likes, views, createdAt.
limitNoResults per page (max 100).
response_formatNomarkdown for reading, json for further processing.markdown

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint and non-destructive, so the safety profile is covered. The description adds value beyond that: it states the return shape (deck summaries with a deck ID), the pagination limit (max 100), and the default response format.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose sentence, then tight Args list and two concrete examples. Every line earns its place and the format is scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by stating what comes back (deck summaries, deck ID) and where to go next. Pagination, defaults, and sort semantics are all covered, so an agent has enough to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds genuine meaning: q is explained to span deck name, description AND legend name, so a champion query finds decks even when the title omits it. It also clarifies sort/dir pairing and what response_format is for.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Search) and resource (public decklists on Piltover Archive), and adds the intent behind it (seeing how a champion/archetype is built). It also differentiates from the sibling piltover_get_deck by explaining it returns summaries whose deck ID feeds that tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for when to use it ('see how a champion or archetype is actually built, what the community is playing right now') and explicit example query->arg mappings. It routes to piltover_get_deck for the full card list, though it doesn't explicitly distinguish itself from piltover_search_cards.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 5 tool updatesv0.1.0
    • First observedpiltover_get_cards
    • First observedpiltover_get_deck
    • First observedpiltover_list_sets
    • First observedpiltover_search_cards
    • First observedpiltover_search_decks

TDQS

A4.6/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: search vs. identity lookup for cards, list sets, search vs. fetch for decks. The descriptions even include explicit 'Don't use when' guidance steering between the card-search and card-get pair, which is the only plausible overlap.

Naming Consistency5/5

All five tools follow a strict piltover_<verb>_<noun> snake_case pattern (search_cards, get_cards, list_sets, search_decks, get_deck). Search/get/list verbs are used consistently and distinguish the operations predictably.

Tool Count5/5

Five tools is well-scoped for a read-only card and deck archive: two for cards, one for sets, two for decks. No bloat, and no single tool is doing unrelated work.

Completeness4/5

The surface covers the core lifecycle for a read-only archive: card search, identity resolution, set enumeration, deck search, and full deck retrieval, with resolution of deck UUIDs built in. Minor gaps remain (e.g. no explicit rulings/price-history or set-contents browsing beyond the search filter), but these are workable via piltover_search_cards.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables Claude to search and retrieve Magic: The Gathering card details, prices, set information, and random cards from Scryfall's database through natural language.
    4
    2
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides AI assistants with access to Magic: The Gathering card data via Scryfall API, enabling card search, image downloads, and database management.
    10
    2
    Apache 2.0
  • F
    license
    Not graded
    quality
    A
    maintenance
    Provides Magic: The Gathering card, deck, provider, and statistical evidence tools for LLMs to make informed deckbuilding decisions.
    -