uranium-tools-mcp
Version:
MCP for Uranium NFT tools to mint, list, and manage digital assets on the permaweb.
1 lines • 22.2 kB
JavaScript
import{StdioServerTransport as e}from"@modelcontextprotocol/sdk/server/stdio.js";import{Server as t}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as n,ListToolsRequestSchema as r}from"@modelcontextprotocol/sdk/types.js";import{z as i}from"zod";import a from"axios";import*as o from"fs";const s={BASE_URL:process.env.URANIUM_BASE_URL||`https://gw.urnm.pro`,TIMEOUT:2e4},c={DEVICE_ID:`mcp-server`,API_KEY:process.env.URANIUM_API_KEY||``},l=a.create({baseURL:s.BASE_URL,timeout:s.TIMEOUT,headers:{"Content-Type":`application/json`}});l.interceptors.request.use(e=>{try{let t=c.API_KEY;t?e.headers[`x-auth-token`]=t:console.warn(`No API key found in environment variables`)}catch(e){console.warn(`Could not get API key from environment:`,e)}return e});const u=e=>e&&typeof e==`object`&&`signal`in e?e.signal:e,d=(e,t)=>({...e??{},signal:e?.signal??u(t)}),f=e=>e,p=e=>e;async function m(e,t,n){let r=d(t,n);return(await l({...r,...e})).data}const h=f({list:(e,...t)=>m({url:`/contracts/list`,method:`GET`},...t),create:(e,...t)=>m({url:`/contracts/create`,method:`POST`,data:e},...t),getById:(e,...t)=>{throw Error(`TODO: Implement contracts.getById when API specification is available`)}}),g=f({list:(e,t,n)=>{let r=new URLSearchParams;return e.contractId&&r.append(`contractId`,e.contractId),e.pageSize&&r.append(`pageSize`,e.pageSize.toString()),e.page&&r.append(`page`,e.page.toString()),r.append(`sortBy`,e.sortBy??`createdAt`),r.append(`order`,e.order??`asc`),e.quickFilter&&r.append(`quickFilter`,e.quickFilter),m({method:`GET`,url:`/assets/?${r.toString()}`},t,n)},prepareNewFile:(e,t,n)=>m({method:`POST`,url:`/assets/prepare-new-file`,data:e},t,n),completeUpload:(e,t,n)=>m({method:`POST`,url:`/assets/complete-upload`,data:e},t,n),startMinting:(e,t,n)=>m({method:`POST`,url:`/assets/start-minting`,data:e},t,n),getById:(e,...t)=>{throw Error(`TODO: Implement assets.getById when API specification is available`)}}),_=f({getMe:(e,...t)=>m({url:`/clients-account/me`,method:`POST`,data:e},...t)});let v=function(e){return e.Image=`image`,e.Video=`video`,e.Gif=`gif`,e.Unknown=`unknown`,e}({}),y=function(e){return e.Camera=`camera`,e.Gallery=`gallery`,e.Upload=`upload`,e}({}),b=function(e){return e[e.STRING=0]=`STRING`,e[e.NUMBER=1]=`NUMBER`,e[e.BOOLEAN=2]=`BOOLEAN`,e[e.UNRECOGNIZED=-1]=`UNRECOGNIZED`,e}({});const x=p({account:_,contracts:h,assets:g}),S=/^(?=[a-zA-Z0-9._\-\[\]]{3,30}$)(?!.*[_.\-\[\]]{2})[^_.\-\[\]].*[^_.\-\[\]]$/gm,C=/^(?=[a-zA-Z0-9_]{3,30}$)(?!.*[_]{2})[^_].*[^_]$/gm;i.object({});async function w(){try{let e=await x.account.getMe({deviceId:c.DEVICE_ID});if(e.status!==`ok`||!e.ok)return{success:!1,error:`Failed to get user account information`};let t=e.ok,n=t.role===`ADMIN`,r=t.userId,i=n?10:5,a=await x.contracts.list(null);if(a.status!==`ok`)return{success:!1,error:a.errorCode||`Failed to load collections`};let o=a.data||[],s=o.filter(e=>e.type!==`EXTERNAL`&&r===e.userId).map(e=>({id:e.id,name:e.name,symbol:e.symbol,type:e.type,status:e.status,ercType:e.ercType,assetCount:e.count??0,address:e.address||void 0,createdAt:e.createdAt?new Date(e.createdAt.seconds*1e3).toISOString():void 0})),l=o.filter(e=>e.type===`EXTERNAL`).map(e=>({id:e.id,name:e.name,symbol:e.symbol,type:e.type,status:e.status,ercType:e.ercType,assetCount:e.count??0,address:e.address||void 0})),u=o.filter(e=>e.type!==`EXTERNAL`&&r!==e.userId).map(e=>({id:e.id,name:e.name,symbol:e.symbol,type:e.type,status:e.status,ercType:e.ercType,assetCount:e.count??0,address:e.address||void 0}));return{success:!0,data:{personalCollections:s,commonCollections:l,externalCollections:u,limits:{personal:{current:s.length,max:i,canCreateMore:s.length<i}}}}}catch(e){return{success:!1,error:e instanceof Error?e.message:`Unknown error occurred`}}}function T(e){if(!e||!e.seconds)return`Unknown`;try{return new Date(e.seconds*1e3).toLocaleDateString()}catch(e){return console.warn(`Failed to format date:`,e),`Invalid date`}}function E(e){return e?e.length<10?e:`${e.slice(0,6)}...${e.slice(-4)}`:`N/A`}const D=i.object({name:i.string().regex(S,`Name must be between 3 and 30 characters long and can contain only letters, numbers and [_.-] symbols`),symbol:i.string().regex(C,`Identifier must be between 3 and 30 characters long and can contain only letters, numbers and underscores`),type:i.enum([`ERC721`,`ERC1155`])}),O=i.object({title:i.string().min(3,`Title must be at least 3 characters long`).max(120,`Title must be no more than 120 characters long`),description:i.string().max(255,`Description must be no more than 255 characters long`).optional(),location:i.string().max(100,`Location must be no more than 100 characters long`).optional(),contractId:i.string().min(1,`Please select a collection`),editions:i.number().min(1,`Editions must be at least 1`).max(1e3,`Editions must be no more than 1000`).optional(),shareWithCommunity:i.boolean().optional().default(!1),filePath:i.string().optional(),fileData:i.string().optional(),fileName:i.string().optional(),mimeType:i.string().optional()}).refine(e=>e.filePath||e.fileData&&e.fileName&&e.mimeType,{message:`Either filePath OR (fileData + fileName + mimeType) must be provided`,path:[`filePath`]});let k=function(e){return e[e.MEDIA_UPLOAD_INITIALIZING=0]=`MEDIA_UPLOAD_INITIALIZING`,e[e.MEDIA_UPLOADING=1]=`MEDIA_UPLOADING`,e[e.MEDIA_VERIFYING=2]=`MEDIA_VERIFYING`,e[e.MEDIA_CONFIRMING=3]=`MEDIA_CONFIRMING`,e[e.MEDIA_CONFIRMED=4]=`MEDIA_CONFIRMED`,e[e.META_UPLOAD_INITIALIZING=5]=`META_UPLOAD_INITIALIZING`,e[e.META_UPLOADING=6]=`META_UPLOADING`,e[e.META_VERIFYING=7]=`META_VERIFYING`,e[e.META_CONFIRMING=8]=`META_CONFIRMING`,e[e.META_CONFIRMED=9]=`META_CONFIRMED`,e[e.NFT_INITIALIZING=10]=`NFT_INITIALIZING`,e[e.NFT_SIGNING=11]=`NFT_SIGNING`,e[e.NFT_MINTING=12]=`NFT_MINTING`,e[e.NFT_CONFIRMED=13]=`NFT_CONFIRMED`,e[e.NFT_ALL_BLOCK_CONFIRMED=14]=`NFT_ALL_BLOCK_CONFIRMED`,e}({}),A=function(e){return e.MEDIA_UPLOAD_INITIALIZING=`MEDIA_UPLOAD_INITIALIZING`,e.MEDIA_UPLOADING=`MEDIA_UPLOADING`,e.MEDIA_VERIFYING=`MEDIA_VERIFYING`,e.MEDIA_CONFIRMING=`MEDIA_CONFIRMING`,e.MEDIA_CONFIRMED=`MEDIA_CONFIRMED`,e.META_UPLOAD_INITIALIZING=`META_UPLOAD_INITIALIZING`,e.META_UPLOADING=`META_UPLOADING`,e.META_VERIFYING=`META_VERIFYING`,e.META_CONFIRMING=`META_CONFIRMING`,e.META_CONFIRMED=`META_CONFIRMED`,e.NFT_INITIALIZING=`NFT_INITIALIZING`,e.NFT_SIGNING=`NFT_SIGNING`,e.NFT_MINTING=`NFT_MINTING`,e.NFT_CONFIRMED=`NFT_CONFIRMED`,e.NFT_ALL_BLOCK_CONFIRMED=`NFT_ALL_BLOCK_CONFIRMED`,e}({});const j=e=>{let t=k[e];if(!t||t===`UNRECOGNIZED`)throw Error(`UNRECOGNIZED_ASSET_STATUS`);return A[t]},M=e=>{switch(j(e)){case A.MEDIA_UPLOAD_INITIALIZING:return`Initializing permanentizer...`;case A.MEDIA_UPLOADING:return`Uploading media...`;case A.MEDIA_VERIFYING:return`Verifying upload...`;case A.MEDIA_CONFIRMING:return`Confirming...`;case A.MEDIA_CONFIRMED:return`Irreversible upload finalized.`;case A.META_UPLOAD_INITIALIZING:return`Initializing permanentizer...`;case A.META_UPLOADING:return`Uploading metadata...`;case A.META_VERIFYING:return`Verifying upload...`;case A.META_CONFIRMING:return`Confirming...`;case A.META_CONFIRMED:return`Irreversible upload finalized.`;case A.NFT_INITIALIZING:return`Mapping smart-contract methods...`;case A.NFT_SIGNING:return`Signing Transaction...`;case A.NFT_MINTING:return`Minting NFT...`;case A.NFT_CONFIRMED:return`NFT minted.`;case A.NFT_ALL_BLOCK_CONFIRMED:return`All blocks confirmed.`;default:return`Unknown status`}},N=e=>{let t=j(e);return t===A.NFT_CONFIRMED||t===A.NFT_ALL_BLOCK_CONFIRMED},P=i.object({contractId:i.string().optional().describe(`Filter assets by collection ID`),page:i.number().min(1).default(1).describe(`Page number (default: 1)`),pageSize:i.number().min(1).max(100).default(20).describe(`Number of assets per page (default: 20, max: 100)`),sortBy:i.string().default(`createdAt`).describe(`Sort field (default: createdAt)`),order:i.enum([`asc`,`desc`]).default(`asc`).describe(`Sort order (default: asc)`),quickFilter:i.string().optional().describe(`Search text to filter assets by title`)});async function F(e){try{let t=await x.assets.list({contractId:e.contractId,page:e.page,pageSize:e.pageSize,sortBy:e.sortBy??`createdAt`,order:e.order??`asc`,quickFilter:e.quickFilter});if(t.status!==`ok`||!t.ok)return{success:!1,error:t.errorCode||`Failed to load assets`};let n=t.ok.data||[],r=t.ok.meta,i=n.map(e=>({id:e.id,title:e.title,description:e.description||void 0,collectionName:e.collectionName,contractId:e.contractId,status:e.status.toString(),statusText:M(e.status),isMinted:N(e.status),mediaType:e.mediaType,ercContractType:e.ercContractType,currentEditions:e.currentEditions,totalEditions:e.editions,thumbnailUrl:e.thumbnailUrl||void 0,sourceUrl:e.sourceUrl,contractAddress:e.contractAddress||void 0,tokenId:e.tokenId||void 0,openSeaUrl:e.openSeaUrl||void 0,creatorName:e.creatorName,creatorAddress:E(e.creatorAddress),currentOwnerName:e.currentOwnerName||void 0,currentOwnerAddress:E(e.currentOwnerAddress),location:e.location||void 0,isEncrypted:e.isEncrypted,isListed:e.isListed,inTransfer:e.inTransfer,createdAt:e.createdAt?T(e.createdAt):void 0,mintedAt:e.mintedAt?T(e.mintedAt):void 0})),a=r?{page:r.page,pageSize:r.pageSize,total:r.total,totalPages:r.countPages,hasNextPage:r.page<r.countPages,hasPreviousPage:r.page>1}:{page:e.page,pageSize:e.pageSize,total:i.length,totalPages:1,hasNextPage:!1,hasPreviousPage:!1};return{success:!0,data:{assets:i,pagination:a}}}catch(e){return{success:!1,error:e instanceof Error?e.message:`Unknown error occurred`}}}const I=D;async function L(e){try{let t=I.parse(e),n=await x.account.getMe({deviceId:c.DEVICE_ID});if(n.status!==`ok`||!n.ok)return{success:!1,error:`Failed to get user account information`};let r=n.ok,i=r.role===`ADMIN`,a=r.userId,o=i?10:5,s=await x.contracts.list(null);if(s.status!==`ok`)return{success:!1,error:`Failed to check existing collections`};if((s.data||[]).filter(e=>e.type!==`EXTERNAL`&&a===e.userId).length>=o)return{success:!1,error:`You have reached the limit of ${o} collections`};let l=await x.contracts.create({name:t.name,symbol:t.symbol,type:t.type});if(l.status!==`ok`||!l.data)return{success:!1,error:l.errorCode||`Failed to create collection`};let u=l.data;return{success:!0,data:{collection:{id:u.id,name:u.name,symbol:u.symbol,type:u.type,status:u.status,ercType:u.ercType,address:u.address||void 0,createdAt:u.createdAt?new Date(u.createdAt.seconds*1e3).toISOString():void 0},message:`Collection "${u.name}" created successfully!`}}}catch(e){return e instanceof i.ZodError?{success:!1,error:`Validation error: ${e.issues.map(e=>e.message).join(`, `)}`}:{success:!1,error:e instanceof Error?e.message:`Unknown error occurred`}}}const R=e=>{let t=e.etag||e.ETag||e.etag;return t?typeof t==`string`?t:t.toString():`""`},z=async e=>{let{url:t,data:n,onProgress:r,signal:i}=e,o=await a.request({method:`PUT`,url:t,data:n,signal:i,onUploadProgress:e=>{if(e.total){let t=e.loaded/e.total;r(t)}}});if(o.status!==200)throw Error(`Failed to upload chunk`);return JSON.parse(R(o.headers))},B=e=>e.startsWith(`image/`)?e===`image/gif`?v.Gif:v.Image:e.startsWith(`video/`)?v.Video:v.Unknown;var V=class{file=null;fileId=null;fileType=null;metadata=null;status=`idle`;progress=0;error=null;totalChunks=0;currentChunk=0;completedChunks=[];uploadInfo=null;constructor(e){this.options=e}reset(){this.file=null,this.fileId=null,this.fileType=null,this.metadata=null,this.status=`idle`,this.progress=0,this.error=null,this.totalChunks=0,this.currentChunk=0,this.completedChunks=[],this.uploadInfo=null}async prepareUpload(e){let{file:t,metadata:n,fileType:r,source:i,deviceId:a}=e;this.status=`preparing`,this.error=null,this.file=t,this.fileType=r;try{let e=await x.assets.prepareNewFile({metadata:n,deviceId:a,type:r,source:i,fileSize:t.size,isPrivate:this.options?.isPrivate});if(e.status!==`ok`)throw Error(`Failed to prepare file upload`);return this.fileId=e.fileId,this.uploadInfo={chunkCount:e.chunkCount,chunkSize:e.chunkSize,fileUploadId:e.fileUploadId,uploadPartUrls:e.uploadPartUrls},this.totalChunks=e.chunkCount,e}catch(e){throw this.status=`error`,this.error=e instanceof Error?e:Error(String(e)),e}}isNodeFile(e){return`buffer`in e}async uploadChunk(e){if(!this.file||!this.uploadInfo)throw Error(`File or upload info not available`);this.currentChunk=e+1;let t=this.uploadInfo.uploadPartUrls[e];if(!t)throw Error(`Invalid chunk index`);let{url:n,partNumber:r}=t,{chunkSize:i}=this.uploadInfo,a=e*i,o=Math.min(a+i,this.file.size),s=await this.file.slice(a,o).arrayBuffer(),c=3;for(;c>0;)try{let t={eTag:await z({url:n,data:s,onProgress:t=>{this.progress=(e+t)/this.uploadInfo.chunkCount}}),partNumber:r};return this.completedChunks.push(t),t}catch(t){if(c--,c===0)throw this.status=`error`,this.error=t instanceof Error?t:Error(String(t)),Error(`Failed to upload chunk ${e+1}`)}throw Error(`Failed to upload chunk ${e+1} - all retries exhausted`)}async uploadAllChunks(){if(!this.uploadInfo)throw Error(`Upload info not available`);this.status=`uploading`;let e=[];for(let t=0;t<this.uploadInfo.chunkCount;t++)try{let n=await this.uploadChunk(t);e.push(n)}catch(e){throw this.status=`error`,e}return e}async finalizeUpload(){if(!this.fileId||!this.file||this.completedChunks.length===0)throw Error(`Missing data for upload finalization`);this.status=`finalizing`;try{let e=await x.assets.completeUpload({fileId:this.fileId,chunks:this.completedChunks,mimeType:this.file.type,disableThumbnail:this.options?.disableThumbnail});if(e.status!==`ok`)throw Error(`Failed to finalize upload`);return this.status=`completed`,e}catch(e){throw this.status=`error`,this.error=e instanceof Error?e:Error(String(e)),e}}};const H=B,U=O;function W(e){let t=e.split(`.`).pop()?.toLowerCase();return t&&{jpg:`image/jpeg`,jpeg:`image/jpeg`,png:`image/png`,gif:`image/gif`,webp:`image/webp`,svg:`image/svg+xml`,mp4:`video/mp4`,webm:`video/webm`,mov:`video/quicktime`,avi:`video/x-msvideo`,mp3:`audio/mpeg`,wav:`audio/wav`,ogg:`audio/ogg`,pdf:`application/pdf`,txt:`text/plain`}[t]||`application/octet-stream`}function G(e){if(!o.existsSync(e))throw Error(`File does not exist: ${e}`);let t=o.readFileSync(e),n=o.statSync(e),r=e.split(`/`).pop()||`unknown`,i=W(r);return{buffer:t,name:r,size:t.length,type:i,lastModified:n.mtime.getTime(),slice(e,t){let n=this.buffer.subarray(e,t);return{arrayBuffer(){let e=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);return Promise.resolve(e)}}}}}function K(e,t,n){try{let r=e.replace(/^data:[^;]+;base64,/,``),i=Buffer.from(r,`base64`);if(i.length===0)throw Error(`Invalid base64 data: resulted in empty buffer`);return{buffer:i,name:t,size:i.length,type:n,lastModified:Date.now(),slice(e,t){let n=this.buffer.subarray(e,t);return{arrayBuffer(){let e=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);return Promise.resolve(e)}}}}}catch(e){throw Error(`Failed to create file from base64 data: ${e instanceof Error?e.message:`Unknown error`}`)}}async function q(e){try{let t=U.parse(e),n;if(t.fileData&&t.fileName&&t.mimeType)n=K(t.fileData,t.fileName,t.mimeType);else if(t.filePath){if(!o.existsSync(t.filePath))return{success:!1,error:`File not found: ${t.filePath}`};n=G(t.filePath)}else return{success:!1,error:`Either filePath or (fileData + fileName + mimeType) must be provided`};let r=H(n.type);if(r===v.Unknown)return{success:!1,error:`Unsupported file type: ${n.type}`};let i=new V({disableThumbnail:!1,isPrivate:!1}),a=JSON.stringify({lastModified:n.lastModified,size:n.size,type:n.type,name:n.name});if(await i.prepareUpload({file:n,metadata:a,fileType:r,source:y.Upload,deviceId:c.DEVICE_ID}),!i.fileId)throw Error(`Failed to prepare file upload`);await i.uploadAllChunks(),await i.finalizeUpload();let s=await x.assets.startMinting({fileId:i.fileId,editions:t.editions,contractId:t.contractId,shareWithCommunity:t.shareWithCommunity??!1,isEncrypted:!1,metadata:{attributes:[{key:`title`,value:t.title,type:b.STRING},...t.description?[{key:`description`,value:t.description,type:b.STRING}]:[],...t.location?[{key:`location`,value:t.location,type:b.STRING}]:[],{key:`appName`,value:`Uranium MCP`,type:b.STRING},{key:`appVersion`,value:`1.0.0`,type:b.STRING}]}});return s.status===`ok`?{success:!0,data:{asset:{fileId:i.fileId,contractId:t.contractId,title:t.title,description:t.description,location:t.location,editions:t.editions,shareWithCommunity:t.shareWithCommunity},message:`Asset "${t.title}" created successfully and is being minted!`,progress:{stage:`Minting NFT...`,percentage:100}}}:{success:!1,error:s.errorCode||`Failed to start minting`}}catch(e){return e instanceof i.ZodError?{success:!1,error:`Validation error: ${e.issues.map(e=>e.message).join(`, `)}`}:{success:!1,error:e instanceof Error?e.message:`Unknown error occurred`}}}var J=[{name:`list_collections`,description:`List all user collections (personal, common, and external)`,inputSchema:{type:`object`,properties:{},required:[]}},{name:`list_assets`,description:`List assets with optional filtering by collection, search, and pagination`,inputSchema:{type:`object`,properties:{contractId:{type:`string`,description:`Filter assets by collection ID`},page:{type:`number`,description:`Page number (default: 1)`,default:1,minimum:1},pageSize:{type:`number`,description:`Number of assets per page (default: 20, max: 100)`,default:20,minimum:1,maximum:100},sortBy:{type:`string`,description:`Sort field (default: createdAt)`,default:`createdAt`},order:{type:`string`,enum:[`asc`,`desc`],description:`Sort order (default: asc)`,default:`asc`},quickFilter:{type:`string`,description:`Search text to filter assets by title`}},required:[]}},{name:`create_collection`,description:`Create a new NFT collection`,inputSchema:{type:`object`,properties:{name:{type:`string`,description:`Collection name (3-30 characters, letters, numbers, and [_.-] symbols)`,minLength:3,maxLength:30},symbol:{type:`string`,description:`Collection symbol (3-30 characters, letters, numbers, and underscores)`,minLength:3,maxLength:30},type:{type:`string`,enum:[`ERC721`,`ERC1155`],description:`Collection type: ERC721 (single NFTs) or ERC1155 (multi-token)`}},required:[`name`,`symbol`,`type`]}},{name:`create_asset`,description:`Create a new NFT asset from a local file or base64 data`,inputSchema:{type:`object`,properties:{filePath:{type:`string`,description:`Absolute path to the media file (for local files)`},fileData:{type:`string`,description:`Base64 encoded file data (for Claude Desktop)`},fileName:{type:`string`,description:`Original filename (required when using fileData)`},mimeType:{type:`string`,description:`MIME type of the file (required when using fileData, e.g., 'image/png')`},contractId:{type:`string`,description:`ID of the collection to mint the asset in`},title:{type:`string`,description:`Asset title (3-120 characters)`,minLength:3,maxLength:120},description:{type:`string`,description:`Asset description (optional, max 255 characters)`,maxLength:255},location:{type:`string`,description:`Location where the asset was created (optional, max 100 characters)`,maxLength:100},editions:{type:`number`,description:`Number of editions (for ERC1155 collections only, 1-1000)`,minimum:1,maximum:1e3},shareWithCommunity:{type:`boolean`,description:`Make the asset discoverable by the community (optional, default: false)`,default:!1}},required:[`contractId`,`title`]}}],Y={name:`uranium-tools-mcp`,version:`1.0.8`,title:`Uranium MCP`,description:`MCP for Uranium NFT tools to mint, list, and manage digital assets on the permaweb.`,main:`build/index.js`,bin:{"uranium-tools-mcp":`cli.js`},module:`./src/index.ts`,mcpName:`io.github.xkelxmc/uranium-mcp`,license:`MIT`,type:`module`,files:[`build`,`README.md`,`cli.js`],repository:{type:`git`,url:`git+https://github.com/xkelxmc/uranium-mcp.git`},homepage:`https://github.com/xkelxmc/uranium-mcp#readme`,scripts:{"build:dev":`rm -rf build && tsdown && chmod 755 cli.js`,build:`rm -rf build && tsdown --minify && chmod 755 cli.js`,start:`node build/index.js`,dev:`tsdown --watch`,clean:`rm -rf build`,prettier:`prettier --write .`,"mcp:stdio":`npm run build:dev && TRANSPORT_MODE=stdio node build/index.js`,"mcp:http":`npm run build:dev && TRANSPORT_MODE=http node build/index.js`,"mcp:inspect":`npm run build:dev && (TRANSPORT_MODE=http node build/index.js &) && sleep 2 && npx @modelcontextprotocol/inspector http://localhost:3000/mcp`,"dev:stdio":`npm run build:dev && npx @modelcontextprotocol/inspector -e TRANSPORT_MODE=stdio -e DEBUG=true node build/index.js`,"dev:http":`npm run build:dev && DEBUG=true TRANSPORT_MODE=http node build/index.js`,"generate:readme":`node utils/generate-readme.js`,"publish-mcp-to-registry":`mcp-publisher publish`,"pub:release":`pnpm build && npm publish`},keywords:[`mcp`,`uranium`,`nft`,`blockchain`,`assets`,`collections`],author:{name:`uranium`},dependencies:{"@modelcontextprotocol/sdk":`^1.0.0`,axios:`^1.11.0`,zod:`^4.0.17`},devDependencies:{"@types/node":`^22.13.10`,tsdown:`^0.14.1`,tsx:`4.20.5`,typescript:`5.9.2`,prettier:`^3.5.3`},engines:{node:`>=18.0.0`}};const X=new t({name:Y.name,title:Y.title,version:Y.version},{capabilities:{tools:{}}});X.setRequestHandler(r,async()=>({tools:J})),X.setRequestHandler(n,async e=>{let{name:t,arguments:n}=e.params;try{switch(t){case`list_collections`:{let e=await w();return{content:[{type:`text`,text:JSON.stringify(e,null,2)}]}}case`list_assets`:{let e=P.parse(n||{}),t=await F(e);return{content:[{type:`text`,text:JSON.stringify(t,null,2)}]}}case`create_collection`:{let e=I.parse(n),t=await L(e);return{content:[{type:`text`,text:JSON.stringify(t,null,2)}]}}case`create_asset`:{let e=U.parse(n),t=await q(e);return{content:[{type:`text`,text:JSON.stringify(t,null,2)}]}}default:throw Error(`Unknown tool: ${t}`)}}catch(e){let t=e instanceof Error?e.message:`Unknown error occurred`;return{content:[{type:`text`,text:JSON.stringify({success:!1,error:t},null,2)}],isError:!0}}});async function Z(){process.env.URANIUM_API_KEY||(console.error(`Error: URANIUM_API_KEY environment variable is required`),process.exit(1));let t=new e;try{await X.connect(t),console.error(`Uranium MCP Server started successfully`)}catch(e){console.error(`Failed to start server:`,e),process.exit(1)}}Z().catch(e=>{console.error(`Unhandled error:`,e),process.exit(1)});export{};