export_buddy_card
Export your buddy card as an SVG image file. Specify the output path.
Instructions
Export your full buddy card as an SVG image file.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Output file path (default: ./buddy-{name}-card.svg in current directory) |
Implementation Reference
- src/mcp/tools/export.ts:142-158 (handler)The handler function for the export_buddy_card tool. It takes an optional 'path' argument, retrieves the current buddy from S.currentBuddy, builds card lines via buildCardLines(), converts to SVG via buildSvg(), and writes the result to a file.
handler: async (args: Record<string, unknown>) => { S.petBuddyStreak = 0; S.lastToolCalled = 'export_buddy_card'; if (!S.currentBuddy) return 'Initialize a buddy first!'; const b = S.currentBuddy; const borderColor = RARITY_HEX[b.rarity] ?? '#FFFFFF'; const outputPath = args['path'] ? resolve(String(args['path'])) : resolve(`buddy-${sanitizeName(b.name ?? 'buddy')}-card.svg`); try { writeFileSync(outputPath, buildSvg(buildCardLines(b), borderColor)); return `✅ Card exported to: ${outputPath}`; } catch (err: unknown) { return `❌ Export failed: ${(err as Error).message}`; } }, - src/mcp/tools/export.ts:128-141 (schema)The tool definition object containing name 'export_buddy_card', description, and inputSchema (with optional 'path' string property).
const exportBuddyCardTool = { tool: { name: 'export_buddy_card', description: 'Export your full buddy card as an SVG image file.', inputSchema: { type: 'object' as const, properties: { path: { type: 'string', description: 'Output file path (default: ./buddy-{name}-card.svg in current directory)', }, }, }, }, - src/mcp/tools/export.ts:203-211 (registration)Registration of the export_buddy_card tool into the dynamicTools Map via dynamicTools.set(). Also includes metadata in _def.
dynamicTools.set('export_buddy_card', { ...exportBuddyCardTool, _def: { toolName: 'export_buddy_card', description: 'Core: Export Card SVG', logic: 'N/A', scope: 'global', }, }); - src/mcp/tools/export.ts:84-85 (helper)buildCardLines() helper: builds the text-based card layout (borders, stats, sprite, name, bio) from ProfileData for rendering into SVG.
function buildCardLines(b: ProfileData): string[] { const dg = b.stats['DEBUGGING'] ?? 0; - src/mcp/tools/export.ts:36-82 (helper)buildSvg() helper: converts text lines into an SVG with monospace font, black background, colored borders/rarity based on rarity color.
function buildSvg(lines: string[], borderColor: string = '#FFFFFF'): string { const maxLen = Math.max(...lines.map((l) => l.length), 1); const width = Math.ceil(maxLen * CHAR_WIDTH) + PAD_X * 2; const height = Math.ceil(lines.length * LINE_HEIGHT) + PAD_Y * 2; const tspans = lines .map((line, i) => { const y = PAD_Y + (i + 1) * LINE_HEIGHT; const isBorderLine = line.startsWith('╭') || line.startsWith('╰'); if (isBorderLine) { return ` <tspan x="${PAD_X}" y="${y}" fill="${borderColor}">${escapeXml(line)}</tspan>`; } const isRarityLine = line.includes('★★'); if (isRarityLine) { return ` <tspan x="${PAD_X}" y="${y}" fill="${borderColor}">${escapeXml(line)}</tspan>`; } const isSpriteContent = /[()[\]/\\_.~`|^=<>:;,@*+ω-]/.test(line); if (isSpriteContent && line.includes('│')) { const parts = line.split('│'); const colored = parts .map((part) => escapeXml(part)) .join(`<tspan fill="${borderColor}">│</tspan>`); return ` <tspan x="${PAD_X}" y="${y}" fill="${borderColor}">${colored}</tspan>`; } if (line.includes('│')) { const parts = line.split('│'); const colored = parts .map((part) => escapeXml(part)) .join(`<tspan fill="${borderColor}">│</tspan>`); return ` <tspan x="${PAD_X}" y="${y}">${colored}</tspan>`; } if (!line.includes('│') && !isBorderLine) { return ` <tspan x="${PAD_X}" y="${y}" fill="${borderColor}">${escapeXml(line)}</tspan>`; } return ` <tspan x="${PAD_X}" y="${y}">${escapeXml(line)}</tspan>`; }) .join('\n'); return [ `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">`, ` <rect width="${width}" height="${height}" fill="#000000" stroke="#FFFFFF" stroke-width="2" rx="10"/>`, ` <text font-family="'Cascadia Code','Fira Code','Courier New',monospace" font-size="${FONT_SIZE}" fill="#cdd6f4" xml:space="preserve">`, tspans, ` </text>`, `</svg>`, ].join('\n'); }