csb_parse_deck_text
Parse plain-text decklists into individual Magic: The Gathering cards for use with Commander Spellbook tools.
Instructions
Parse a plain-text decklist into cards using Commander Spellbook.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Plain-text deck list, e.g. '1x Sol Ring' per line |
Implementation Reference
- src/mcp-server.ts:425-437 (registration)Registration of the csb_parse_deck_text MCP tool, including input/output schemas and the handler function that delegates to CSB.parseCardListFromText for the actual parsing logic.server.registerTool( "csb_parse_deck_text", { title: "CSB: Parse deck text", description: "Parse a plain-text decklist into cards using Commander Spellbook.", inputSchema: csbParseDeckInput, outputSchema: csbParseDeckOutput }, async ({ text }: { text: string }) => { const res = (await CSB.parseCardListFromText(text)) as any; return { structuredContent: res } as any; } );
- src/mcp-server.ts:418-424 (schema)Zod input schema (deck text) and output schema (parsed main deck and optional commanders with card names and quantities).const csbParseDeckInput = { text: z.string().min(1).describe("Plain-text deck list, e.g. '1x Sol Ring' per line") } as const; const csbParseDeckOutput = { main: z.array(z.object({ card: z.string(), quantity: z.number().int().positive() })), commanders: z.array(z.object({ card: z.string(), quantity: z.number().int().positive() })).optional() } as const;
- src/csb.ts:110-110 (handler)Handler function on CSB object that sends the deck text via POST to the Commander Spellbook API endpoint /card-list-from-text to parse it into structured card list.parseCardListFromText: (text: string) => postText("/card-list-from-text", text),
- src/csb.ts:71-107 (helper)Rate-limited, retrying POST request helper used by CSB.parseCardListFromText to communicate with the Commander Spellbook backend API.async function postText(path: string, body: string) { const base = process.env.CSB_BASE_URL || DEFAULT_BASE_URL; const url = new URL(path, base); const maxRetries = Number(process.env.CSB_MAX_RETRIES || 3); const retryBaseMs = Number(process.env.CSB_RETRY_BASE_MS || 250); for (let attempt = 0; attempt <= maxRetries; attempt++) { await acquireSlot(); const res = await fetch(url, { method: "POST", headers: { "Content-Type": "text/plain", "User-Agent": "scryfall-mcp/0.1 (commanderspellbook client)" }, body }); if (res.status === 429) { const retryAfter = Number(res.headers.get("Retry-After") || 0); const backoff = retryAfter > 0 ? retryAfter * 1000 : retryBaseMs * Math.pow(2, attempt); if (attempt < maxRetries) { await sleep(backoff); continue; } } if (!res.ok) { const text = await res.text().catch(() => ""); throw new Error(`CSB request failed: ${res.status} ${res.statusText} - ${text}`); } return res.json() as Promise<unknown>; } throw new Error("CSB request failed after retries"); }