create_badge
Create customizable digital badge templates with custom fields, branding, and optional expiration dates for issuing certificates and credentials.
Instructions
Create a new badge template with optional custom fields and branding. This badge can then be issued to recipients.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| badge_logo_path | No | Path to badge logo file (jpeg,png,jpg,gif,svg, max 2MB) | |
| comment | No | Additional comments or notes about the badge | |
| custom_fields | No | Custom fields for this badge (e.g., completion date, score, instructor) | |
| description | Yes | Badge description (e.g., "Awarded for completing the full-stack web development course") | |
| expire_date | No | Badge expiration date in YYYY-MM-DD format (optional) | |
| idempotency_key | Yes | Unique key to prevent duplicate badge creation (e.g., "badge_webdev_2024_001") | |
| issuing_organization_name | Yes | Name of the issuing organization (e.g., "Tech Academy") | |
| left_panel_description | No | Additional description for the left panel of the certificate | |
| name | Yes | Badge name (e.g., "Web Development Certificate") | |
| nickname | No | Optional badge nickname or short name | |
| organization_id | No | Existing organization ID (optional, will create new organization if not provided) |
Implementation Reference
- src/index.ts:191-231 (handler)The core handler function in IssueBadgeClient that performs the actual API call to create a badge, handling both JSON payloads and file uploads for badge logos.async createBadge(data: z.infer<typeof CreateBadgeSchema>): Promise<CreatedBadge> { const { badge_logo_path, ...badgeData } = data; if (badge_logo_path) { // Handle file upload const formData = new FormData(); // Add file try { const fileBuffer = readFileSync(badge_logo_path); const fileName = badge_logo_path.split('/').pop() || 'badge_logo.png'; formData.append('badge_logo', fileBuffer, { filename: fileName, }); } catch (error) { throw new Error(`Failed to read badge logo file: ${error}`); } // Add other fields Object.entries(badgeData).forEach(([key, value]) => { if (value !== undefined) { if (key === 'custom_fields') { formData.append(key, JSON.stringify(value)); } else { formData.append(key, String(value)); } } }); const response = await this.client.post('/badge/create', formData, { headers: { ...formData.getHeaders(), }, }); return response.data; } else { // JSON request without file const response = await this.client.post('/badge/create', badgeData); return response.data; } }
- src/index.ts:82-98 (schema)Zod schema for validating inputs to the create_badge tool.const CreateBadgeSchema = z.object({ name: z.string().describe('Badge name'), description: z.string().describe('Badge description'), issuing_organization_name: z.string().describe('Name of the issuing organization'), idempotency_key: z.string().describe('Unique key to prevent duplicate badge creation'), nickname: z.string().optional().describe('Optional badge nickname'), left_panel_description: z.string().optional().describe('Additional description for left panel'), organization_id: z.string().optional().describe('Existing organization ID'), comment: z.string().optional().describe('Additional comments'), expire_date: z.string().optional().describe('Badge expiration date (YYYY-MM-DD)'), badge_logo_path: z.string().optional().describe('Path to badge logo file'), custom_fields: z.array(z.object({ name: z.string().describe('Field name'), type: z.enum(['text', 'email', 'number', 'date']).default('text').describe('Field type'), required: z.boolean().default(false).describe('Whether field is required'), })).optional().describe('Custom fields for this badge'), });
- src/index.ts:313-388 (registration)MCP tool registration including name, description, and input schema for create_badge.{ name: 'create_badge', description: 'Create a new badge template with optional custom fields and branding. This badge can then be issued to recipients.', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Badge name (e.g., "Web Development Certificate")', }, description: { type: 'string', description: 'Badge description (e.g., "Awarded for completing the full-stack web development course")', }, issuing_organization_name: { type: 'string', description: 'Name of the issuing organization (e.g., "Tech Academy")', }, idempotency_key: { type: 'string', description: 'Unique key to prevent duplicate badge creation (e.g., "badge_webdev_2024_001")', }, nickname: { type: 'string', description: 'Optional badge nickname or short name', }, left_panel_description: { type: 'string', description: 'Additional description for the left panel of the certificate', }, organization_id: { type: 'string', description: 'Existing organization ID (optional, will create new organization if not provided)', }, comment: { type: 'string', description: 'Additional comments or notes about the badge', }, expire_date: { type: 'string', pattern: '^\\d{4}-\\d{2}-\\d{2}$', description: 'Badge expiration date in YYYY-MM-DD format (optional)', }, badge_logo_path: { type: 'string', description: 'Path to badge logo file (jpeg,png,jpg,gif,svg, max 2MB)', }, custom_fields: { type: 'array', description: 'Custom fields for this badge (e.g., completion date, score, instructor)', items: { type: 'object', properties: { name: { type: 'string', description: 'Field name (e.g., "Completion Date")', }, type: { type: 'string', enum: ['text', 'email', 'number', 'date'], description: 'Field type', default: 'text', }, required: { type: 'boolean', description: 'Whether this field is required when issuing the badge', default: false, }, }, required: ['name'], }, }, }, required: ['name', 'description', 'issuing_organization_name', 'idempotency_key'], }, },
- src/index.ts:482-505 (handler)The MCP server request handler that validates inputs, calls the createBadge API method, and formats the response for the create_badge tool.case 'create_badge': { const validatedArgs = CreateBadgeSchema.parse(args); const result = await apiClient.createBadge(validatedArgs); if (result.success) { return { content: [ { type: 'text', text: `✨ Badge Created Successfully!\n\n🏷️ Badge Name: ${validatedArgs.name}\n🆔 Badge ID: ${result.badgeId}\n🏢 Organization ID: ${result.organizationId}\n\nYou can now issue this badge to recipients using the badge ID.\n\n${JSON.stringify(result, null, 2)}`, }, ], }; } return { content: [ { type: 'text', text: `🎨 Badge Creation Result:\n\n${JSON.stringify(result, null, 2)}`, }, ], }; }