mint-day 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -11,11 +11,6 @@ import { mintSchema, handleMint } from "./tools/mint.js";
11
11
  import { mintCheckSchema, handleMintCheck } from "./tools/mint-check.js";
12
12
  import { mintResolveSchema, handleMintResolve } from "./tools/mint-resolve.js";
13
13
  dotenv.config();
14
- // Testnet try-it wallet (Base Sepolia, pre-funded)
15
- const TRYIT_KEY = "";
16
- const TRYIT_CONTRACT = "0xa52450397f312c256Bd68B202C0CF90387Ea0E67";
17
- const TRYIT_RPC = "https://sepolia.base.org";
18
- const TRYIT_CHAIN = 84532;
19
14
  const MAINNET_CONTRACT = "0x12a1c11a0b2860f64e7d8df20989f97d40de7f2c";
20
15
  const MAINNET_RPC = "https://mainnet.base.org";
21
16
  const MAINNET_CHAIN = 8453;
@@ -33,7 +28,7 @@ function loadPrivateKey() {
33
28
  }
34
29
  const userKey = loadPrivateKey();
35
30
  const hasUserKey = !!userKey;
36
- // Mainnet by default. Testnet only when no private key AND no recipient provided (decided per-call).
31
+ // Mainnet configuration
37
32
  const chainId = parseInt(process.env.CHAIN_ID || String(hasUserKey ? MAINNET_CHAIN : MAINNET_CHAIN));
38
33
  const contractAddress = process.env.MINT_FACTORY_ADDRESS || MAINNET_CONTRACT;
39
34
  const rpcUrl = process.env.BASE_RPC_URL || MAINNET_RPC;
@@ -54,12 +49,7 @@ const server = new McpServer({
54
49
  name: "mint-day",
55
50
  version: "0.4.0",
56
51
  });
57
- server.tool("mint", "Create a permanent, verifiable on-chain record on Base. Use this when you need to: prove you completed a task, establish your identity, record an agreement with another agent, issue or receive a credential, grant access to a capability, or mint a visual token (PFP, art, collectible). Supports two protocols: 'mintday' (default, gas-sponsored) and 'superrare' (Rare Protocol, requires PRIVATE_KEY). Set platform: 'superrare' to mint on Rare Protocol contracts. The token is immutable and publicly verifiable. Provide an image URL, local file path, or base64 for visual tokens. Returns a preview with mintId first; call again with mintId to confirm.", mintSchema, async (params) => handleMint(params, calldataService, defaultRecipient, userKey, {
58
- tryitKey: TRYIT_KEY,
59
- tryitContract: TRYIT_CONTRACT,
60
- tryitRpc: TRYIT_RPC,
61
- tryitChain: TRYIT_CHAIN,
62
- }));
52
+ server.tool("mint", "Create a permanent, verifiable on-chain record on Base. Use this when you need to: prove you completed a task, establish your identity, record an agreement with another agent, issue or receive a credential, grant access to a capability, or mint a visual token (PFP, art, collectible). Supports two protocols: 'mintday' (default, gas-sponsored) and 'superrare' (Rare Protocol, requires PRIVATE_KEY). Set platform: 'superrare' to mint on Rare Protocol contracts. The token is immutable and publicly verifiable. Provide an image URL, local file path, or base64 for visual tokens. Returns a preview with mintId first; call again with mintId to confirm.", mintSchema, async (params) => handleMint(params, calldataService, defaultRecipient, userKey));
63
53
  server.tool("mint_check", "Look up mint.day tokens. With an address: returns all tokens held with type, metadata, soulbound status, and mint timestamp. Without an address: returns global stats (total minted, current fee). Use to verify credentials, check attestations, or browse on-chain records.", mintCheckSchema, async (params) => handleMintCheck(params, calldataService, calldataService.provider, contractAddress, chainId));
64
54
  server.tool("mint_resolve", "Resolve an agent's on-chain identity. Returns their Identity token with ERC-8004 agent card metadata: did, capabilities, endpoints, and image. Use this before transacting with another agent to verify who they are.", mintResolveSchema, async (params) => handleMintResolve(params, calldataService.provider, contractAddress, chainId));
65
55
  async function main() {
@@ -20,12 +20,6 @@ export declare const mintSchema: {
20
20
  mintday: "mintday";
21
21
  }>>;
22
22
  };
23
- interface TryitConfig {
24
- tryitKey: string;
25
- tryitContract: string;
26
- tryitRpc: string;
27
- tryitChain: number;
28
- }
29
23
  export declare function handleMint(params: {
30
24
  description?: string;
31
25
  tokenType?: string;
@@ -36,10 +30,9 @@ export declare function handleMint(params: {
36
30
  mintId?: string;
37
31
  metadata?: Record<string, unknown>;
38
32
  platform?: string;
39
- }, calldataService: CalldataService, defaultRecipient: string, userKey?: string, tryit?: TryitConfig): Promise<{
33
+ }, calldataService: CalldataService, defaultRecipient: string, userKey?: string): Promise<{
40
34
  content: {
41
35
  type: "text";
42
36
  text: string;
43
37
  }[];
44
38
  }>;
45
- export {};
@@ -3,7 +3,6 @@ import { z } from "zod";
3
3
  import { ethers } from "ethers";
4
4
  import { TokenType, TOKEN_TYPE_NAMES } from "../types.js";
5
5
  import { classifyIntent } from "../services/classifier.js";
6
- import { CalldataService } from "../services/calldata.js";
7
6
  import { resolveImage } from "../services/image-upload.js";
8
7
  import { mintOnRareProtocol } from "../services/rare-protocol.js";
9
8
  // Intent cache: preview mintId -> frozen intent + platform
@@ -102,7 +101,7 @@ async function sponsoredMint(result, recipient) {
102
101
  return { error: `Sponsor request failed: ${message}` };
103
102
  }
104
103
  }
105
- export async function handleMint(params, calldataService, defaultRecipient, userKey = "", tryit = { tryitKey: "", tryitContract: "", tryitRpc: "", tryitChain: 84532 }) {
104
+ export async function handleMint(params, calldataService, defaultRecipient, userKey = "") {
106
105
  // Confirmation path: replay cached intent
107
106
  // Check cache first so we can use cached recipient for mode detection
108
107
  if (params.mintId) {
@@ -120,8 +119,7 @@ export async function handleMint(params, calldataService, defaultRecipient, user
120
119
  intentCache.delete(params.mintId);
121
120
  // Mode detection using cached recipient
122
121
  const hasRecipient = !!cached.recipient;
123
- const isTestnet = !userKey && !hasRecipient;
124
- const privateKey = userKey || (isTestnet ? tryit.tryitKey : "");
122
+ const privateKey = userKey;
125
123
  // Rare Protocol path: mint via SuperRare contracts on Base
126
124
  if (cachedPlatform === "superrare") {
127
125
  if (!privateKey) {
@@ -133,7 +131,7 @@ export async function handleMint(params, calldataService, defaultRecipient, user
133
131
  };
134
132
  }
135
133
  try {
136
- const rareResult = await mintOnRareProtocol(cached, privateKey, isTestnet);
134
+ const rareResult = await mintOnRareProtocol(cached, privateKey, false);
137
135
  return {
138
136
  content: [{
139
137
  type: "text",
@@ -151,17 +149,11 @@ export async function handleMint(params, calldataService, defaultRecipient, user
151
149
  };
152
150
  }
153
151
  }
154
- // Use testnet calldataService if in try-it mode
155
- let activeCalldataService = calldataService;
156
- if (isTestnet) {
157
- activeCalldataService = new CalldataService(tryit.tryitRpc, tryit.tryitContract, tryit.tryitChain);
158
- }
159
- const result = await activeCalldataService.buildMintCalldata(cached);
152
+ const result = await calldataService.buildMintCalldata(cached);
160
153
  // If we have a private key, sign and submit directly
161
154
  if (privateKey) {
162
155
  try {
163
- const provider = isTestnet ? activeCalldataService.provider : calldataService.provider;
164
- const wallet = new ethers.Wallet(privateKey, provider);
156
+ const wallet = new ethers.Wallet(privateKey, calldataService.provider);
165
157
  const tx = await wallet.sendTransaction({
166
158
  to: result.to,
167
159
  data: result.calldata,
@@ -177,12 +169,9 @@ export async function handleMint(params, calldataService, defaultRecipient, user
177
169
  tokenType: result.tokenType,
178
170
  soulbound: result.soulbound,
179
171
  recipient: cached.recipient,
180
- chain: isTestnet ? "Base Sepolia (testnet)" : "Base",
181
- explorer: `https://${result.chainId === 8453 ? "" : "sepolia."}basescan.org/tx/${receipt.hash}`,
172
+ chain: "Base",
173
+ explorer: `https://basescan.org/tx/${receipt.hash}`,
182
174
  };
183
- if (isTestnet) {
184
- response.note = "This token was minted on Base Sepolia (testnet). To mint on Base mainnet, save a private key to ~/.mint-day/credentials and restart the MCP server.";
185
- }
186
175
  return {
187
176
  content: [{
188
177
  type: "text",
@@ -256,8 +245,6 @@ export async function handleMint(params, calldataService, defaultRecipient, user
256
245
  };
257
246
  }
258
247
  const recipient = params.recipient || defaultRecipient;
259
- const hasRecipient = !!recipient;
260
- const isTestnet = !userKey && !hasRecipient;
261
248
  if (!recipient) {
262
249
  return {
263
250
  content: [{
@@ -386,12 +373,7 @@ export async function handleMint(params, calldataService, defaultRecipient, user
386
373
  preview.missingFields = intent.missingFields;
387
374
  preview.hint = "Identity tokens (ERC-8004) should include capabilities[], endpoints[], and did. Provide these in metadata for full compliance.";
388
375
  }
389
- if (isTestnet) {
390
- preview.chain = "Base Sepolia (testnet)";
391
- }
392
- else {
393
- preview.chain = "Base";
394
- }
376
+ preview.chain = "Base";
395
377
  preview.instruction = "Call mint with mintId to confirm.";
396
378
  return {
397
379
  content: [{ type: "text", text: JSON.stringify(preview, null, 2) }],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mint-day",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Agent-native minting on Base. One tool call, any token type.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -13,11 +13,6 @@ import { mintResolveSchema, handleMintResolve } from "./tools/mint-resolve.js";
13
13
 
14
14
  dotenv.config();
15
15
 
16
- // Testnet try-it wallet (Base Sepolia, pre-funded)
17
- const TRYIT_KEY = "";
18
- const TRYIT_CONTRACT = "0xa52450397f312c256Bd68B202C0CF90387Ea0E67";
19
- const TRYIT_RPC = "https://sepolia.base.org";
20
- const TRYIT_CHAIN = 84532;
21
16
  const MAINNET_CONTRACT = "0x12a1c11a0b2860f64e7d8df20989f97d40de7f2c";
22
17
  const MAINNET_RPC = "https://mainnet.base.org";
23
18
  const MAINNET_CHAIN = 8453;
@@ -36,7 +31,7 @@ function loadPrivateKey(): string {
36
31
  const userKey = loadPrivateKey();
37
32
  const hasUserKey = !!userKey;
38
33
 
39
- // Mainnet by default. Testnet only when no private key AND no recipient provided (decided per-call).
34
+ // Mainnet configuration
40
35
  const chainId = parseInt(process.env.CHAIN_ID || String(hasUserKey ? MAINNET_CHAIN : MAINNET_CHAIN));
41
36
  const contractAddress = process.env.MINT_FACTORY_ADDRESS || MAINNET_CONTRACT;
42
37
  const rpcUrl = process.env.BASE_RPC_URL || MAINNET_RPC;
@@ -69,12 +64,7 @@ server.tool(
69
64
  "mint",
70
65
  "Create a permanent, verifiable on-chain record on Base. Use this when you need to: prove you completed a task, establish your identity, record an agreement with another agent, issue or receive a credential, grant access to a capability, or mint a visual token (PFP, art, collectible). Supports two protocols: 'mintday' (default, gas-sponsored) and 'superrare' (Rare Protocol, requires PRIVATE_KEY). Set platform: 'superrare' to mint on Rare Protocol contracts. The token is immutable and publicly verifiable. Provide an image URL, local file path, or base64 for visual tokens. Returns a preview with mintId first; call again with mintId to confirm.",
71
66
  mintSchema,
72
- async (params) => handleMint(params, calldataService, defaultRecipient, userKey, {
73
- tryitKey: TRYIT_KEY,
74
- tryitContract: TRYIT_CONTRACT,
75
- tryitRpc: TRYIT_RPC,
76
- tryitChain: TRYIT_CHAIN,
77
- }),
67
+ async (params) => handleMint(params, calldataService, defaultRecipient, userKey),
78
68
  );
79
69
 
80
70
  server.tool(
package/src/tools/mint.ts CHANGED
@@ -69,13 +69,6 @@ export const mintSchema = {
69
69
  .describe("Which protocol to mint on. 'mintday' uses the MintFactory contract (default). 'superrare' mints via Rare Protocol on Base."),
70
70
  };
71
71
 
72
- interface TryitConfig {
73
- tryitKey: string;
74
- tryitContract: string;
75
- tryitRpc: string;
76
- tryitChain: number;
77
- }
78
-
79
72
  const SPONSOR_URL = process.env.SPONSOR_URL || "https://www.mint.day/api/sponsor";
80
73
 
81
74
  async function sponsoredMint(result: { to: string; calldata: string; value: string; estimatedGas: number; tokenType: string; soulbound: boolean; chainId: number }, recipient: string): Promise<Record<string, unknown> | null> {
@@ -131,7 +124,6 @@ export async function handleMint(
131
124
  calldataService: CalldataService,
132
125
  defaultRecipient: string,
133
126
  userKey: string = "",
134
- tryit: TryitConfig = { tryitKey: "", tryitContract: "", tryitRpc: "", tryitChain: 84532 },
135
127
  ) {
136
128
  // Confirmation path: replay cached intent
137
129
  // Check cache first so we can use cached recipient for mode detection
@@ -151,8 +143,7 @@ export async function handleMint(
151
143
 
152
144
  // Mode detection using cached recipient
153
145
  const hasRecipient = !!cached.recipient;
154
- const isTestnet = !userKey && !hasRecipient;
155
- const privateKey = userKey || (isTestnet ? tryit.tryitKey : "");
146
+ const privateKey = userKey;
156
147
 
157
148
  // Rare Protocol path: mint via SuperRare contracts on Base
158
149
  if (cachedPlatform === "superrare") {
@@ -165,7 +156,7 @@ export async function handleMint(
165
156
  };
166
157
  }
167
158
  try {
168
- const rareResult = await mintOnRareProtocol(cached, privateKey, isTestnet);
159
+ const rareResult = await mintOnRareProtocol(cached, privateKey, false);
169
160
  return {
170
161
  content: [{
171
162
  type: "text" as const,
@@ -183,18 +174,12 @@ export async function handleMint(
183
174
  }
184
175
  }
185
176
 
186
- // Use testnet calldataService if in try-it mode
187
- let activeCalldataService = calldataService;
188
- if (isTestnet) {
189
- activeCalldataService = new CalldataService(tryit.tryitRpc, tryit.tryitContract, tryit.tryitChain);
190
- }
191
- const result = await activeCalldataService.buildMintCalldata(cached);
177
+ const result = await calldataService.buildMintCalldata(cached);
192
178
 
193
179
  // If we have a private key, sign and submit directly
194
180
  if (privateKey) {
195
181
  try {
196
- const provider = isTestnet ? activeCalldataService.provider : calldataService.provider;
197
- const wallet = new ethers.Wallet(privateKey, provider);
182
+ const wallet = new ethers.Wallet(privateKey, calldataService.provider);
198
183
  const tx = await wallet.sendTransaction({
199
184
  to: result.to,
200
185
  data: result.calldata,
@@ -210,12 +195,9 @@ export async function handleMint(
210
195
  tokenType: result.tokenType,
211
196
  soulbound: result.soulbound,
212
197
  recipient: cached.recipient,
213
- chain: isTestnet ? "Base Sepolia (testnet)" : "Base",
214
- explorer: `https://${result.chainId === 8453 ? "" : "sepolia."}basescan.org/tx/${receipt!.hash}`,
198
+ chain: "Base",
199
+ explorer: `https://basescan.org/tx/${receipt!.hash}`,
215
200
  };
216
- if (isTestnet) {
217
- response.note = "This token was minted on Base Sepolia (testnet). To mint on Base mainnet, save a private key to ~/.mint-day/credentials and restart the MCP server.";
218
- }
219
201
  return {
220
202
  content: [{
221
203
  type: "text" as const,
@@ -292,9 +274,6 @@ export async function handleMint(
292
274
  }
293
275
 
294
276
  const recipient = params.recipient || defaultRecipient;
295
- const hasRecipient = !!recipient;
296
- const isTestnet = !userKey && !hasRecipient;
297
-
298
277
  if (!recipient) {
299
278
  return {
300
279
  content: [{
@@ -423,11 +402,7 @@ export async function handleMint(
423
402
  preview.missingFields = intent.missingFields;
424
403
  preview.hint = "Identity tokens (ERC-8004) should include capabilities[], endpoints[], and did. Provide these in metadata for full compliance.";
425
404
  }
426
- if (isTestnet) {
427
- preview.chain = "Base Sepolia (testnet)";
428
- } else {
429
- preview.chain = "Base";
430
- }
405
+ preview.chain = "Base";
431
406
  preview.instruction = "Call mint with mintId to confirm.";
432
407
 
433
408
  return {