csb_lookup_by_oracle_ids
Map Scryfall oracle_id UUIDs to Commander Spellbook numeric IDs using a local index that builds automatically when stale.
Instructions
Map Scryfall oracle_id UUIDs to Commander Spellbook numeric IDs using the local index (builds if stale).
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| oracleIds | Yes |
Implementation Reference
- src/csb-index.ts:79-89 (handler)Core handler function that loads the CSB index (building if necessary) and maps input oracle IDs to CSB numeric card IDs, returning found mappings and missing IDs.export async function lookupCsbIdsByOracle(oracleIds: string[], options?: { ttlMs?: number; force?: boolean; cachePath?: string }): Promise<{ found: Record<string, number>; missing: string[] }> { const idx = await loadCsbIndex(options); const found: Record<string, number> = {}; const missing: string[] = []; for (const oid of oracleIds) { const id = idx.oracleToId[oid]; if (typeof id === "number") found[oid] = id; else missing.push(oid); } return { found, missing }; }
- src/mcp-server.ts:539-540 (schema)Zod schemas defining tool input (array of oracle UUIDs) and output (object with found oracleId->CSB ID map and array of missing oracle IDs).const csbLookupOracleInput = { oracleIds: z.array(z.string().uuid()).min(1) } as const; const csbLookupOracleOutput = { found: z.record(z.string(), z.number().int()), missing: z.array(z.string()) } as const;
- src/mcp-server.ts:541-553 (registration)Registers the MCP tool 'csb_lookup_by_oracle_ids' with schemas and a thin async handler that delegates to lookupCsbIdsByOracle.server.registerTool( "csb_lookup_by_oracle_ids", { title: "CSB: Lookup by oracle IDs", description: "Map Scryfall oracle_id UUIDs to Commander Spellbook numeric IDs using the local index (builds if stale).", inputSchema: csbLookupOracleInput, outputSchema: csbLookupOracleOutput }, async ({ oracleIds }: { oracleIds: string[] }) => { const res = await lookupCsbIdsByOracle(oracleIds); return { structuredContent: res } as any; } );
- src/csb-index.ts:58-77 (helper)Helper that loads or builds the oracle-to-CSB-ID index from memory/disk cache, respecting TTL and force options.export async function loadCsbIndex(options?: { ttlMs?: number; force?: boolean; cachePath?: string }): Promise<CsbCardIndex> { const ttl = options?.ttlMs ?? DEFAULT_TTL_MS; const cachePath = options?.cachePath ?? DEFAULT_CACHE_PATH; const now = Date.now(); if (!options?.force && memCache && now - memCache.at < ttl) return memCache.data; if (!options?.force) { const disk = await readCsbIndex(cachePath); if (disk && now - disk.at < ttl) { memCache = { at: disk.at, data: disk.data }; return disk.data; } } const data = await buildCsbIndex(); memCache = { at: now, data }; await writeCsbIndex(data, cachePath).catch(() => {}); return data; }
- src/csb-index.ts:36-56 (helper)Helper that builds the full index by paginating all CSB cards and mapping oracle IDs to CSB IDs.export async function buildCsbIndex(): Promise<CsbCardIndex> { const oracleToId: Record<string, number> = Object.create(null); const limit = 100; let offset = 0; let total = 0; while (true) { const page: any = await CSB.cards({ limit, offset }); const results: any[] = Array.isArray(page?.results) ? page.results : []; total = Number(page?.count ?? total); for (const c of results) { const oid = c?.oracleId; const id = c?.id; if (typeof oid === "string" && typeof id === "number") { if (!(oid in oracleToId)) oracleToId[oid] = id; } } if (!page?.next || results.length === 0) break; offset += limit; } return { builtAtMs: Date.now(), total, oracleToId }; }