create_asset
Create NFT assets by uploading files or base64 data to specified collections, supporting both ERC721 and ERC1155 standards with customizable metadata.
Instructions
Create a new NFT asset from a local file or base64 data
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filePath | No | Absolute path to the media file (for local files) | |
| fileData | No | Base64 encoded file data (for Claude Desktop) | |
| fileName | No | Original filename (required when using fileData) | |
| mimeType | No | MIME type of the file (required when using fileData, e.g., 'image/png') | |
| contractId | Yes | ID of the collection to mint the asset in | |
| title | Yes | Asset title (3-120 characters) | |
| description | No | Asset description (optional, max 255 characters) | |
| location | No | Location where the asset was created (optional, max 100 characters) | |
| editions | No | Number of editions (for ERC1155 collections only, 1-1000) | |
| shareWithCommunity | No | Make the asset discoverable by the community (optional, default: false) |
Implementation Reference
- src/tools/create-asset.ts:128-282 (handler)The core handler function that executes the create_asset tool: parses input, handles file input from path or base64, performs upload using UploadPrimitives, and initiates NFT minting via api.assets.startMinting.export async function createAsset(params: CreateAssetInput): Promise<CreateAssetResult> { try { // Validate input using our schema const validatedParams = createAssetInputSchema.parse(params); // Determine how to create the file - either from disk or base64 data let file: NodeFileData; if (validatedParams.fileData && validatedParams.fileName && validatedParams.mimeType) { // Option 1: Create file from base64 data (for Claude Desktop) file = createNodeFileFromData(validatedParams.fileData, validatedParams.fileName, validatedParams.mimeType); } else if (validatedParams.filePath) { // Option 2: Create file from disk path if (!fs.existsSync(validatedParams.filePath)) { return { success: false, error: `File not found: ${validatedParams.filePath}`, }; } file = createNodeFileFromPath(validatedParams.filePath); } else { return { success: false, error: "Either filePath or (fileData + fileName + mimeType) must be provided", }; } const fileType = detectFileTypeFromMimeType(file.type); if (fileType === FileType.Unknown) { return { success: false, error: `Unsupported file type: ${file.type}`, }; } // Create upload primitives instance const uploader = new UploadPrimitives({ disableThumbnail: false, isPrivate: false, }); // Stage 1: Prepare upload const fileMetadata = JSON.stringify({ lastModified: file.lastModified, size: file.size, type: file.type, name: file.name, }); await uploader.prepareUpload({ file, metadata: fileMetadata, fileType, source: FileSource.Upload, deviceId: MCP_CONFIG.DEVICE_ID, }); if (!uploader.fileId) { throw new Error("Failed to prepare file upload"); } // Stage 2: Upload all chunks await uploader.uploadAllChunks(); // Stage 3: Finalize upload await uploader.finalizeUpload(); // Stage 4: Start minting const mintResponse = await api.assets.startMinting({ fileId: uploader.fileId, editions: validatedParams.editions, contractId: validatedParams.contractId, shareWithCommunity: validatedParams.shareWithCommunity ?? false, isEncrypted: false, // Not supporting encryption in MCP for now metadata: { attributes: [ { key: "title", value: validatedParams.title, type: Metadata_AttributeType.STRING, }, ...(validatedParams.description ? [ { key: "description", value: validatedParams.description, type: Metadata_AttributeType.STRING, }, ] : []), ...(validatedParams.location ? [ { key: "location", value: validatedParams.location, type: Metadata_AttributeType.STRING, }, ] : []), { key: "appName", value: "Uranium MCP", type: Metadata_AttributeType.STRING, }, { key: "appVersion", value: "1.0.0", type: Metadata_AttributeType.STRING, }, ], }, }); if (mintResponse.status !== "ok") { return { success: false, error: mintResponse.errorCode || "Failed to start minting", }; } return { success: true, data: { asset: { fileId: uploader.fileId, contractId: validatedParams.contractId, title: validatedParams.title, description: validatedParams.description, location: validatedParams.location, editions: validatedParams.editions, shareWithCommunity: validatedParams.shareWithCommunity, }, message: `Asset "${validatedParams.title}" created successfully and is being minted!`, progress: { stage: "Minting NFT...", percentage: 100, }, }, }; } catch (error) { if (error instanceof z.ZodError) { const errorMessages = error.issues.map((err) => err.message).join(", "); return { success: false, error: `Validation error: ${errorMessages}`, }; } return { success: false, error: error instanceof Error ? error.message : "Unknown error occurred", }; } }
- src/utils/schemas.ts:20-48 (schema)Zod schema defining the input parameters for createAsset, including validation for title, contractId, file inputs (path or base64), etc.export const createAssetSchema = z .object({ title: z .string() .min(3, "Title must be at least 3 characters long") .max(120, "Title must be no more than 120 characters long"), description: z.string().max(255, "Description must be no more than 255 characters long").optional(), location: z.string().max(100, "Location must be no more than 100 characters long").optional(), contractId: z.string().min(1, "Please select a collection"), editions: z .number() .min(1, "Editions must be at least 1") .max(1000, "Editions must be no more than 1000") .optional(), shareWithCommunity: z.boolean().optional().default(false), // Option 1: File from disk filePath: z.string().optional(), // Option 2: Base64 data (for Claude Desktop) fileData: z.string().optional(), // base64 encoded data fileName: z.string().optional(), // original filename mimeType: z.string().optional(), // MIME type }) .refine((data) => data.filePath || (data.fileData && data.fileName && data.mimeType), { message: "Either filePath OR (fileData + fileName + mimeType) must be provided", path: ["filePath"], // This will show the error on the filePath field });
- src/server.ts:77-89 (registration)MCP server request handler registration for the 'create_asset' tool, which validates arguments and calls the createAsset handler.case "create_asset": { // Validate and parse arguments const validatedArgs = createAssetInputSchema.parse(args); const result = await createAsset(validatedArgs); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; }
- src/tools/create-asset.ts:9-10 (schema)Re-exports the input schema and derives TypeScript type for createAsset.export const createAssetInputSchema = createAssetSchema; export type CreateAssetInput = z.infer<typeof createAssetInputSchema>;
- src/tools/create-asset.ts:12-31 (schema)TypeScript interface defining the return type of createAsset.export interface CreateAssetResult { success: boolean; data?: { asset: { fileId: string; contractId: string; title: string; description?: string; location?: string; editions?: number; shareWithCommunity?: boolean; }; message: string; progress?: { stage: string; percentage?: number; }; }; error?: string; }