neutron-mcp 1.0.2 → 1.0.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/README.md CHANGED
@@ -42,9 +42,8 @@ Add to your config file:
42
42
  "command": "npx",
43
43
  "args": ["-y", "neutron-mcp"],
44
44
  "env": {
45
- "NEUTRON_ACCOUNT_ID": "your_account_id",
46
- "NEUTRON_ACCESS_KEY": "your_access_key",
47
- "NEUTRON_SECRET_KEY": "your_secret_key"
45
+ "NEUTRON_API_KEY": "your_api_key",
46
+ "NEUTRON_API_SECRET": "your_api_secret"
48
47
  }
49
48
  }
50
49
  }
@@ -64,9 +63,8 @@ Add to `~/.claude.json` or your project's `.mcp.json`:
64
63
  "command": "npx",
65
64
  "args": ["-y", "neutron-mcp"],
66
65
  "env": {
67
- "NEUTRON_ACCOUNT_ID": "your_account_id",
68
- "NEUTRON_ACCESS_KEY": "your_access_key",
69
- "NEUTRON_SECRET_KEY": "your_secret_key"
66
+ "NEUTRON_API_KEY": "your_api_key",
67
+ "NEUTRON_API_SECRET": "your_api_secret"
70
68
  }
71
69
  }
72
70
  }
@@ -86,9 +84,8 @@ Add to `.cursor/mcp.json` in your project or global config:
86
84
  "command": "npx",
87
85
  "args": ["-y", "neutron-mcp"],
88
86
  "env": {
89
- "NEUTRON_ACCOUNT_ID": "your_account_id",
90
- "NEUTRON_ACCESS_KEY": "your_access_key",
91
- "NEUTRON_SECRET_KEY": "your_secret_key"
87
+ "NEUTRON_API_KEY": "your_api_key",
88
+ "NEUTRON_API_SECRET": "your_api_secret"
92
89
  }
93
90
  }
94
91
  }
@@ -108,9 +105,8 @@ Add to your Windsurf MCP configuration:
108
105
  "command": "npx",
109
106
  "args": ["-y", "neutron-mcp"],
110
107
  "env": {
111
- "NEUTRON_ACCOUNT_ID": "your_account_id",
112
- "NEUTRON_ACCESS_KEY": "your_access_key",
113
- "NEUTRON_SECRET_KEY": "your_secret_key"
108
+ "NEUTRON_API_KEY": "your_api_key",
109
+ "NEUTRON_API_SECRET": "your_api_secret"
114
110
  }
115
111
  }
116
112
  }
@@ -130,9 +126,8 @@ Add to your Cline MCP settings:
130
126
  "command": "npx",
131
127
  "args": ["-y", "neutron-mcp"],
132
128
  "env": {
133
- "NEUTRON_ACCOUNT_ID": "your_account_id",
134
- "NEUTRON_ACCESS_KEY": "your_access_key",
135
- "NEUTRON_SECRET_KEY": "your_secret_key"
129
+ "NEUTRON_API_KEY": "your_api_key",
130
+ "NEUTRON_API_SECRET": "your_api_secret"
136
131
  }
137
132
  }
138
133
  }
@@ -169,7 +164,7 @@ Once configured, just ask your AI assistant naturally:
169
164
 
170
165
  > "Set up a webhook for transaction notifications"
171
166
 
172
- > "What banks are supported for payouts in Nigeria?"
167
+ > "What banks are supported for payouts in Vietnam?"
173
168
 
174
169
  ---
175
170
 
@@ -194,7 +189,7 @@ Once configured, just ask your AI assistant naturally:
194
189
  | `neutron_create_transaction` | Create payment (Lightning, on-chain, USDT, fiat) |
195
190
  | `neutron_list_transactions` | List transactions with filters |
196
191
  | `neutron_get_transaction` | Get transaction status |
197
- | `neutron_confirm_transaction` | Confirm pending transaction |
192
+ | `neutron_confirm_transaction` | Confirm quoted transaction |
198
193
  | `neutron_cancel_transaction` | Cancel pending transaction |
199
194
 
200
195
  ### Webhooks
@@ -219,7 +214,7 @@ Once configured, just ask your AI assistant naturally:
219
214
  | **Bitcoin Lightning** | Bolt11 invoices, LNURL, Lightning Address |
220
215
  | **Bitcoin On-chain** | Standard BTC transactions |
221
216
  | **Stablecoins** | USDT on Ethereum (ERC20) and Tron (TRC20) |
222
- | **Fiat Payouts** | Bank transfers, Mobile money |
217
+ | **Fiat Payouts** | Bank transfers, Mobile money (VN, NG, KE, GH, etc.) |
223
218
 
224
219
  ---
225
220
 
@@ -232,7 +227,7 @@ Once configured, just ask your AI assistant naturally:
232
227
  > "Create a payment flow where users can pay $10/month in Bitcoin. Generate a Lightning invoice and set up a webhook to activate their account when paid."
233
228
 
234
229
  ### Payout System
235
- > "Build a function to pay out earnings to users. They can choose Lightning address, on-chain Bitcoin, or bank transfer in supported countries."
230
+ > "Build a function to pay out earnings to users in Vietnam. Send VND to their bank account from our BTC balance."
236
231
 
237
232
  ### Treasury Management
238
233
  > "Show me all my wallet balances and recent transactions. Then help me consolidate funds by transferring USDT to my main wallet."
@@ -243,10 +238,9 @@ Once configured, just ask your AI assistant naturally:
243
238
 
244
239
  | Variable | Required | Description |
245
240
  |----------|----------|-------------|
246
- | `NEUTRON_ACCOUNT_ID` | Yes | Your Neutron account ID |
247
- | `NEUTRON_ACCESS_KEY` | Yes | Your Neutron API access key |
248
- | `NEUTRON_SECRET_KEY` | Yes | Your Neutron API secret key |
249
- | `NEUTRON_API_URL` | No | API URL (defaults to `https://enapi.npay.live`) |
241
+ | `NEUTRON_API_KEY` | Yes | Your Neutron API key |
242
+ | `NEUTRON_API_SECRET` | Yes | Your Neutron API secret |
243
+ | `NEUTRON_API_URL` | No | API URL (defaults to `https://enapi.npay.dev`) |
250
244
 
251
245
  ---
252
246
 
package/dist/index.js CHANGED
@@ -6,63 +6,26 @@ import { z } from "zod";
6
6
  import { NeutronClient } from "./neutron-client.js";
7
7
  // Validation schemas
8
8
  const CreateTransactionSchema = z.object({
9
- sourceMethod: z.enum([
10
- "lightning",
11
- "lightning_address",
12
- "lnurl",
13
- "bolt11",
14
- "on_chain",
15
- "eth",
16
- "tron",
17
- "bank",
18
- "mobile_money",
19
- "internal",
20
- ]),
9
+ extRefId: z.string().optional(),
21
10
  sourceCurrency: z.string(),
22
- sourceAmount: z.string().optional(),
23
- sourceWalletId: z.string().optional(),
24
- destMethod: z.enum([
25
- "lightning",
26
- "lightning_address",
27
- "lnurl",
28
- "bolt11",
29
- "on_chain",
30
- "eth",
31
- "tron",
32
- "bank",
33
- "mobile_money",
34
- "internal",
35
- ]),
11
+ sourceAmount: z.number().optional(),
12
+ sourceMethod: z.string(),
13
+ sourceNotes: z.string().optional(),
36
14
  destCurrency: z.string(),
37
- destAmount: z.string().optional(),
38
- destAddress: z.string().optional(),
39
- destLightningAddress: z.string().optional(),
40
- destBolt11: z.string().optional(),
41
- destAccountNumber: z.string().optional(),
42
- destBankCode: z.string().optional(),
43
- destPhoneNumber: z.string().optional(),
15
+ destAmount: z.number().optional(),
16
+ destMethod: z.string(),
17
+ destBankAcctNum: z.string().optional(),
18
+ destInstitutionCode: z.string().optional(),
44
19
  destRecipientName: z.string().optional(),
45
- destCountry: z.string().optional(),
46
- reference: z.string().optional(),
20
+ destCountryCode: z.string().optional(),
21
+ destAddress: z.string().optional(),
22
+ kycType: z.enum(["individual", "business"]).optional(),
47
23
  });
48
24
  const ListTransactionsSchema = z.object({
49
25
  status: z
50
- .enum(["pending", "processing", "completed", "failed", "cancelled"])
51
- .optional(),
52
- method: z
53
- .enum([
54
- "lightning",
55
- "lightning_address",
56
- "lnurl",
57
- "bolt11",
58
- "on_chain",
59
- "eth",
60
- "tron",
61
- "bank",
62
- "mobile_money",
63
- "internal",
64
- ])
26
+ .enum(["quoted", "pending", "processing", "completed", "failed", "cancelled"])
65
27
  .optional(),
28
+ method: z.string().optional(),
66
29
  currency: z.string().optional(),
67
30
  fromDate: z.string().optional(),
68
31
  toDate: z.string().optional(),
@@ -97,19 +60,18 @@ const UpdateWebhookSchema = z.object({
97
60
  });
98
61
  // Initialize Neutron client
99
62
  function createClient() {
100
- const apiUrl = process.env.NEUTRON_API_URL || "https://enapi.npay.live";
101
- const accountId = process.env.NEUTRON_ACCOUNT_ID;
102
- const accessKey = process.env.NEUTRON_ACCESS_KEY;
103
- const secretKey = process.env.NEUTRON_SECRET_KEY;
104
- if (!accountId || !accessKey || !secretKey) {
105
- throw new Error("NEUTRON_ACCOUNT_ID, NEUTRON_ACCESS_KEY, and NEUTRON_SECRET_KEY environment variables are required");
63
+ const apiUrl = process.env.NEUTRON_API_URL || "https://enapi.npay.dev";
64
+ const apiKey = process.env.NEUTRON_API_KEY;
65
+ const apiSecret = process.env.NEUTRON_API_SECRET;
66
+ if (!apiKey || !apiSecret) {
67
+ throw new Error("NEUTRON_API_KEY and NEUTRON_API_SECRET environment variables are required");
106
68
  }
107
- return new NeutronClient({ apiUrl, accountId, accessKey, secretKey });
69
+ return new NeutronClient({ apiUrl, apiKey, apiSecret });
108
70
  }
109
71
  // Create MCP server
110
72
  const server = new Server({
111
73
  name: "neutron-mcp-server",
112
- version: "1.0.0",
74
+ version: "1.0.3",
113
75
  }, {
114
76
  capabilities: {
115
77
  tools: {},
@@ -119,7 +81,7 @@ const server = new Server({
119
81
  const tools = [
120
82
  {
121
83
  name: "neutron_get_account",
122
- description: "Get Neutron account information including name, email, and status",
84
+ description: "Get Neutron account information including display name, status, country, and timezone",
123
85
  inputSchema: {
124
86
  type: "object",
125
87
  properties: {},
@@ -168,7 +130,6 @@ const tools = [
168
130
  type: "string",
169
131
  enum: ["eth", "tron"],
170
132
  description: "Network for USDT address (eth for ERC20, tron for TRC20)",
171
- default: "tron",
172
133
  },
173
134
  },
174
135
  required: [],
@@ -176,106 +137,75 @@ const tools = [
176
137
  },
177
138
  {
178
139
  name: "neutron_create_transaction",
179
- description: `Create a new transaction. Supports Lightning payments (bolt11, LNURL, Lightning Address), Bitcoin on-chain, USDT (ERC20/TRC20), and fiat payouts (bank, mobile money).
140
+ description: `Create a new transaction. Supports Lightning payments, Bitcoin on-chain, USDT, and fiat payouts.
180
141
 
181
- Examples:
182
- - Lightning payment: sourceMethod="internal", destMethod="lightning_address", destLightningAddress="user@wallet.me"
183
- - Bitcoin withdrawal: sourceMethod="internal", destMethod="on_chain", destAddress="bc1q..."
184
- - USDT transfer: sourceMethod="internal", destMethod="tron", destAddress="T..."
185
- - Bank payout: sourceMethod="internal", destMethod="bank", destAccountNumber="...", destBankCode="...", destRecipientName="..."`,
142
+ Example for VND bank payout:
143
+ - sourceCurrency: "BTC", sourceMethod: "lightning", sourceAmount: 0.001
144
+ - destCurrency: "VND", destMethod: "vnd-instant", destAmount: 300000
145
+ - destBankAcctNum: "0123456789", destInstitutionCode: "970422"
146
+ - destRecipientName: "NGUYEN VAN A", destCountryCode: "VN"`,
186
147
  inputSchema: {
187
148
  type: "object",
188
149
  properties: {
189
- sourceMethod: {
150
+ extRefId: {
190
151
  type: "string",
191
- enum: [
192
- "lightning",
193
- "lightning_address",
194
- "lnurl",
195
- "bolt11",
196
- "on_chain",
197
- "eth",
198
- "tron",
199
- "bank",
200
- "mobile_money",
201
- "internal",
202
- ],
203
- description: "Source funding method",
152
+ description: "Your external reference ID for tracking",
204
153
  },
205
154
  sourceCurrency: {
206
155
  type: "string",
207
- description: "Source currency (BTC, USDT, USD, etc.)",
156
+ description: "Source currency (BTC, USDT, etc.)",
208
157
  },
209
158
  sourceAmount: {
210
- type: "string",
211
- description: "Amount to send from source (optional if destAmount specified)",
159
+ type: "number",
160
+ description: "Amount from source",
212
161
  },
213
- sourceWalletId: {
162
+ sourceMethod: {
214
163
  type: "string",
215
- description: "Specific wallet ID to fund from (optional)",
164
+ description: "Source method (lightning, on_chain, internal, etc.)",
216
165
  },
217
- destMethod: {
166
+ sourceNotes: {
218
167
  type: "string",
219
- enum: [
220
- "lightning",
221
- "lightning_address",
222
- "lnurl",
223
- "bolt11",
224
- "on_chain",
225
- "eth",
226
- "tron",
227
- "bank",
228
- "mobile_money",
229
- "internal",
230
- ],
231
- description: "Destination payout method",
168
+ description: "Notes for the source transaction",
232
169
  },
233
170
  destCurrency: {
234
171
  type: "string",
235
- description: "Destination currency",
172
+ description: "Destination currency (VND, USD, BTC, etc.)",
236
173
  },
237
174
  destAmount: {
238
- type: "string",
239
- description: "Amount to receive at destination (optional if sourceAmount specified)",
240
- },
241
- destAddress: {
242
- type: "string",
243
- description: "Destination address (for on_chain, eth, tron)",
244
- },
245
- destLightningAddress: {
246
- type: "string",
247
- description: "Lightning address (e.g., user@wallet.me)",
175
+ type: "number",
176
+ description: "Amount to destination",
248
177
  },
249
- destBolt11: {
178
+ destMethod: {
250
179
  type: "string",
251
- description: "Bolt11 Lightning invoice to pay",
180
+ description: "Destination method (vnd-instant, lightning, on_chain, tron, etc.)",
252
181
  },
253
- destAccountNumber: {
182
+ destBankAcctNum: {
254
183
  type: "string",
255
184
  description: "Bank account number (for bank payouts)",
256
185
  },
257
- destBankCode: {
186
+ destInstitutionCode: {
258
187
  type: "string",
259
- description: "Bank code/routing number",
188
+ description: "Bank/institution code",
260
189
  },
261
- destPhoneNumber: {
190
+ destRecipientName: {
262
191
  type: "string",
263
- description: "Phone number (for mobile money)",
192
+ description: "Recipient full legal name (for fiat payouts)",
264
193
  },
265
- destRecipientName: {
194
+ destCountryCode: {
266
195
  type: "string",
267
- description: "Recipient name for fiat payouts",
196
+ description: "Destination country code (VN, NG, etc.)",
268
197
  },
269
- destCountry: {
198
+ destAddress: {
270
199
  type: "string",
271
- description: "Destination country code (ISO 3166-1 alpha-2)",
200
+ description: "Crypto address (for on_chain, tron, eth)",
272
201
  },
273
- reference: {
202
+ kycType: {
274
203
  type: "string",
275
- description: "Custom reference ID for the transaction",
204
+ enum: ["individual", "business"],
205
+ description: "KYC type for recipient",
276
206
  },
277
207
  },
278
- required: ["sourceMethod", "sourceCurrency", "destMethod", "destCurrency"],
208
+ required: ["sourceCurrency", "sourceMethod", "destCurrency", "destMethod"],
279
209
  },
280
210
  },
281
211
  {
@@ -286,23 +216,18 @@ Examples:
286
216
  properties: {
287
217
  status: {
288
218
  type: "string",
289
- enum: ["pending", "processing", "completed", "failed", "cancelled"],
219
+ enum: [
220
+ "quoted",
221
+ "pending",
222
+ "processing",
223
+ "completed",
224
+ "failed",
225
+ "cancelled",
226
+ ],
290
227
  description: "Filter by transaction status",
291
228
  },
292
229
  method: {
293
230
  type: "string",
294
- enum: [
295
- "lightning",
296
- "lightning_address",
297
- "lnurl",
298
- "bolt11",
299
- "on_chain",
300
- "eth",
301
- "tron",
302
- "bank",
303
- "mobile_money",
304
- "internal",
305
- ],
306
231
  description: "Filter by transaction method",
307
232
  },
308
233
  currency: {
@@ -319,7 +244,7 @@ Examples:
319
244
  },
320
245
  limit: {
321
246
  type: "number",
322
- description: "Number of results to return (default 20)",
247
+ description: "Number of results to return",
323
248
  },
324
249
  offset: {
325
250
  type: "number",
@@ -337,7 +262,7 @@ Examples:
337
262
  properties: {
338
263
  transactionId: {
339
264
  type: "string",
340
- description: "The transaction ID to check",
265
+ description: "The transaction ID (txnId) to check",
341
266
  },
342
267
  },
343
268
  required: ["transactionId"],
@@ -345,7 +270,7 @@ Examples:
345
270
  },
346
271
  {
347
272
  name: "neutron_confirm_transaction",
348
- description: "Confirm a pending transaction to proceed with execution",
273
+ description: "Confirm a quoted transaction to proceed with execution",
349
274
  inputSchema: {
350
275
  type: "object",
351
276
  properties: {
@@ -359,7 +284,7 @@ Examples:
359
284
  },
360
285
  {
361
286
  name: "neutron_cancel_transaction",
362
- description: "Cancel a pending transaction",
287
+ description: "Cancel a pending or quoted transaction",
363
288
  inputSchema: {
364
289
  type: "object",
365
290
  properties: {
@@ -469,7 +394,7 @@ Examples:
469
394
  properties: {
470
395
  country: {
471
396
  type: "string",
472
- description: "Country code (ISO 3166-1 alpha-2, e.g., NG, KE, GH)",
397
+ description: "Country code (ISO 3166-1 alpha-2, e.g., VN, NG, KE, GH)",
473
398
  },
474
399
  },
475
400
  required: ["country"],
@@ -520,30 +445,42 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
520
445
  }
521
446
  case "neutron_create_transaction": {
522
447
  const validated = CreateTransactionSchema.parse(args);
448
+ const reqDetails = {};
449
+ if (validated.destBankAcctNum)
450
+ reqDetails.bankAcctNum = validated.destBankAcctNum;
451
+ if (validated.destInstitutionCode)
452
+ reqDetails.institutionCode = validated.destInstitutionCode;
453
+ if (validated.destAddress)
454
+ reqDetails.address = validated.destAddress;
523
455
  const transaction = await client.createTransaction({
456
+ extRefId: validated.extRefId,
524
457
  sourceReq: {
458
+ ccy: validated.sourceCurrency,
459
+ amtRequested: validated.sourceAmount,
525
460
  method: validated.sourceMethod,
526
- currency: validated.sourceCurrency,
527
- amount: validated.sourceAmount,
528
- walletId: validated.sourceWalletId,
461
+ notes: validated.sourceNotes,
462
+ reqDetails: {},
529
463
  },
530
464
  destReq: {
465
+ ccy: validated.destCurrency,
466
+ amtRequested: validated.destAmount,
531
467
  method: validated.destMethod,
532
- currency: validated.destCurrency,
533
- amount: validated.destAmount,
534
- address: validated.destAddress,
535
- lightningAddress: validated.destLightningAddress,
536
- bolt11: validated.destBolt11,
537
- accountNumber: validated.destAccountNumber,
538
- bankCode: validated.destBankCode,
539
- phoneNumber: validated.destPhoneNumber,
540
- recipientName: validated.destRecipientName,
541
- country: validated.destCountry,
468
+ reqDetails,
469
+ kyc: validated.kycType
470
+ ? {
471
+ type: validated.kycType,
472
+ details: {
473
+ legalFullName: validated.destRecipientName,
474
+ countryCode: validated.destCountryCode,
475
+ },
476
+ }
477
+ : undefined,
542
478
  },
543
- reference: validated.reference,
544
479
  });
545
480
  return {
546
- content: [{ type: "text", text: JSON.stringify(transaction, null, 2) }],
481
+ content: [
482
+ { type: "text", text: JSON.stringify(transaction, null, 2) },
483
+ ],
547
484
  };
548
485
  }
549
486
  case "neutron_list_transactions": {
@@ -558,28 +495,36 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
558
495
  offset: validated.offset,
559
496
  });
560
497
  return {
561
- content: [{ type: "text", text: JSON.stringify(transactions, null, 2) }],
498
+ content: [
499
+ { type: "text", text: JSON.stringify(transactions, null, 2) },
500
+ ],
562
501
  };
563
502
  }
564
503
  case "neutron_get_transaction": {
565
504
  const { transactionId } = args;
566
- const transaction = await client.getTransactionStatus(transactionId);
505
+ const transaction = await client.getTransaction(transactionId);
567
506
  return {
568
- content: [{ type: "text", text: JSON.stringify(transaction, null, 2) }],
507
+ content: [
508
+ { type: "text", text: JSON.stringify(transaction, null, 2) },
509
+ ],
569
510
  };
570
511
  }
571
512
  case "neutron_confirm_transaction": {
572
513
  const { transactionId } = args;
573
514
  const transaction = await client.confirmTransaction(transactionId);
574
515
  return {
575
- content: [{ type: "text", text: JSON.stringify(transaction, null, 2) }],
516
+ content: [
517
+ { type: "text", text: JSON.stringify(transaction, null, 2) },
518
+ ],
576
519
  };
577
520
  }
578
521
  case "neutron_cancel_transaction": {
579
522
  const { transactionId } = args;
580
523
  const transaction = await client.cancelTransaction(transactionId);
581
524
  return {
582
- content: [{ type: "text", text: JSON.stringify(transaction, null, 2) }],
525
+ content: [
526
+ { type: "text", text: JSON.stringify(transaction, null, 2) },
527
+ ],
583
528
  };
584
529
  }
585
530
  case "neutron_create_webhook": {
@@ -613,14 +558,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
613
558
  const { webhookId } = args;
614
559
  await client.deleteWebhook(webhookId);
615
560
  return {
616
- content: [{ type: "text", text: `Webhook ${webhookId} deleted successfully` }],
561
+ content: [
562
+ { type: "text", text: `Webhook ${webhookId} deleted successfully` },
563
+ ],
617
564
  };
618
565
  }
619
566
  case "neutron_get_fiat_institutions": {
620
567
  const { country } = args;
621
568
  const institutions = await client.getFiatInstitutions(country);
622
569
  return {
623
- content: [{ type: "text", text: JSON.stringify(institutions, null, 2) }],
570
+ content: [
571
+ { type: "text", text: JSON.stringify(institutions, null, 2) },
572
+ ],
624
573
  };
625
574
  }
626
575
  default:
@@ -1,12 +1,13 @@
1
1
  import type { NeutronConfig, Account, Wallet, ReceiveAddress, Transaction, CreateTransactionRequest, TransactionListParams, TransactionListResponse, Webhook, CreateWebhookRequest, UpdateWebhookRequest, FiatInstitution } from "./types.js";
2
2
  export declare class NeutronClient {
3
3
  private config;
4
- private token;
4
+ private accountId;
5
+ private accessToken;
5
6
  private tokenExpiry;
6
7
  constructor(config: NeutronConfig);
7
8
  private generateSignature;
9
+ private ensureAuthenticated;
8
10
  private request;
9
- authenticate(): Promise<void>;
10
11
  getAccount(): Promise<Account>;
11
12
  getWallets(): Promise<Wallet[]>;
12
13
  getWallet(walletId: string): Promise<Wallet>;
@@ -14,7 +15,7 @@ export declare class NeutronClient {
14
15
  getUsdtAddress(network?: "eth" | "tron"): Promise<ReceiveAddress>;
15
16
  createTransaction(request: CreateTransactionRequest): Promise<Transaction>;
16
17
  getTransactions(params?: TransactionListParams): Promise<TransactionListResponse>;
17
- getTransactionStatus(transactionId: string): Promise<Transaction>;
18
+ getTransaction(transactionId: string): Promise<Transaction>;
18
19
  confirmTransaction(transactionId: string): Promise<Transaction>;
19
20
  cancelTransaction(transactionId: string): Promise<Transaction>;
20
21
  createWebhook(request: CreateWebhookRequest): Promise<Webhook>;
@@ -1,75 +1,96 @@
1
1
  import crypto from "crypto";
2
2
  export class NeutronClient {
3
3
  config;
4
- token = null;
4
+ accountId = null;
5
+ accessToken = null;
5
6
  tokenExpiry = 0;
6
7
  constructor(config) {
7
8
  this.config = config;
8
9
  }
9
10
  generateSignature(payload) {
10
11
  // HMAC-SHA256 signature: {apiKey}&payload={payload}
11
- const stringToSign = `${this.config.accessKey}&payload=${payload}`;
12
+ const stringToSign = `${this.config.apiKey}&payload=${payload}`;
12
13
  return crypto
13
- .createHmac("sha256", this.config.secretKey)
14
+ .createHmac("sha256", this.config.apiSecret)
14
15
  .update(stringToSign)
15
16
  .digest("hex");
16
17
  }
18
+ async ensureAuthenticated() {
19
+ // Check if we have a valid token
20
+ if (this.accessToken && this.accountId && Date.now() < this.tokenExpiry) {
21
+ return;
22
+ }
23
+ // Authenticate to get accountId and accessToken
24
+ const payload = JSON.stringify({ test: "auth" });
25
+ const signature = this.generateSignature(payload);
26
+ const response = await fetch(`${this.config.apiUrl}/api/v2/authentication/token-signature`, {
27
+ method: "POST",
28
+ headers: {
29
+ "Content-Type": "application/json",
30
+ "X-Api-Key": this.config.apiKey,
31
+ "X-Api-Signature": signature,
32
+ },
33
+ body: payload,
34
+ });
35
+ if (!response.ok) {
36
+ const error = await response.json().catch(() => ({}));
37
+ throw new Error(`Authentication failed: ${response.status} - ${error.message || response.statusText}`);
38
+ }
39
+ const authResult = (await response.json());
40
+ this.accountId = authResult.accountId;
41
+ this.accessToken = authResult.accessToken;
42
+ // Set expiry (parse the expiredAt or default to 1 hour)
43
+ this.tokenExpiry = authResult.expiredAt
44
+ ? new Date(authResult.expiredAt).getTime()
45
+ : Date.now() + 3600000;
46
+ }
17
47
  async request(method, path, body) {
18
- const bodyString = body ? JSON.stringify(body) : "";
19
- const signature = this.generateSignature(bodyString);
48
+ await this.ensureAuthenticated();
20
49
  const headers = {
21
50
  "Content-Type": "application/json",
22
- "X-Api-Key": this.config.accessKey,
23
- "X-Api-Signature": signature,
24
- "account_id": this.config.accountId,
51
+ Authorization: `Bearer ${this.accessToken}`,
25
52
  };
26
- // Add bearer token if authenticated
27
- if (this.token && Date.now() < this.tokenExpiry) {
28
- headers["Authorization"] = `Bearer ${this.token}`;
29
- }
30
- const response = await fetch(`${this.config.apiUrl}${path}`, {
53
+ const url = `${this.config.apiUrl}${path}`;
54
+ const response = await fetch(url, {
31
55
  method,
32
56
  headers,
33
- body: bodyString,
57
+ body: body ? JSON.stringify(body) : undefined,
34
58
  });
35
59
  if (!response.ok) {
36
60
  const error = await response.json().catch(() => ({}));
37
61
  throw new Error(`API Error: ${response.status} - ${error.message || response.statusText}`);
38
62
  }
39
- const result = (await response.json());
40
- if (!result.success && result.error) {
41
- throw new Error(`${result.error.code}: ${result.error.message}`);
42
- }
43
- return result.data;
44
- }
45
- // Authentication
46
- async authenticate() {
47
- const result = await this.request("POST", "/authenticate");
48
- this.token = result.token;
49
- this.tokenExpiry = Date.now() + result.expiresIn * 1000;
63
+ return (await response.json());
50
64
  }
51
65
  // Account Management
52
66
  async getAccount() {
53
- return this.request("GET", "/account");
67
+ await this.ensureAuthenticated();
68
+ return this.request("GET", `/api/v2/account/${this.accountId}`);
54
69
  }
55
70
  async getWallets() {
56
- return this.request("GET", "/account/wallets");
71
+ await this.ensureAuthenticated();
72
+ return this.request("GET", `/api/v2/account/${this.accountId}/wallets`);
57
73
  }
58
74
  async getWallet(walletId) {
59
- return this.request("GET", `/wallet/${walletId}`);
75
+ await this.ensureAuthenticated();
76
+ return this.request("GET", `/api/v2/account/${this.accountId}/wallet/${walletId}`);
60
77
  }
61
78
  // Receive Addresses
62
79
  async getBitcoinAddress() {
63
- return this.request("GET", "/bitcoin/receive-address");
80
+ await this.ensureAuthenticated();
81
+ return this.request("GET", `/api/v2/account/${this.accountId}/bitcoin/receive-address`);
64
82
  }
65
83
  async getUsdtAddress(network = "tron") {
66
- return this.request("GET", `/usdt/receive-address?network=${network}`);
84
+ await this.ensureAuthenticated();
85
+ return this.request("GET", `/api/v2/account/${this.accountId}/usdt/receive-address?network=${network}`);
67
86
  }
68
87
  // Transactions
69
88
  async createTransaction(request) {
70
- return this.request("POST", "/transaction", request);
89
+ await this.ensureAuthenticated();
90
+ return this.request("POST", `/api/v2/account/${this.accountId}/transaction`, request);
71
91
  }
72
92
  async getTransactions(params) {
93
+ await this.ensureAuthenticated();
73
94
  const queryParams = new URLSearchParams();
74
95
  if (params) {
75
96
  Object.entries(params).forEach(([key, value]) => {
@@ -79,32 +100,40 @@ export class NeutronClient {
79
100
  });
80
101
  }
81
102
  const query = queryParams.toString();
82
- return this.request("GET", `/transactions${query ? `?${query}` : ""}`);
103
+ return this.request("GET", `/api/v2/account/${this.accountId}/transactions${query ? `?${query}` : ""}`);
83
104
  }
84
- async getTransactionStatus(transactionId) {
85
- return this.request("GET", `/transaction/${transactionId}/status`);
105
+ async getTransaction(transactionId) {
106
+ await this.ensureAuthenticated();
107
+ return this.request("GET", `/api/v2/account/${this.accountId}/transaction/${transactionId}`);
86
108
  }
87
109
  async confirmTransaction(transactionId) {
88
- return this.request("PUT", `/transaction/${transactionId}/confirm`);
110
+ await this.ensureAuthenticated();
111
+ return this.request("PUT", `/api/v2/account/${this.accountId}/transaction/${transactionId}/confirm`);
89
112
  }
90
113
  async cancelTransaction(transactionId) {
91
- return this.request("PATCH", `/transaction/${transactionId}`);
114
+ await this.ensureAuthenticated();
115
+ return this.request("DELETE", `/api/v2/account/${this.accountId}/transaction/${transactionId}`);
92
116
  }
93
117
  // Webhooks
94
118
  async createWebhook(request) {
95
- return this.request("POST", "/webhook", request);
119
+ await this.ensureAuthenticated();
120
+ return this.request("POST", `/api/v2/account/${this.accountId}/webhook`, request);
96
121
  }
97
122
  async getWebhooks() {
98
- return this.request("GET", "/webhooks");
123
+ await this.ensureAuthenticated();
124
+ return this.request("GET", `/api/v2/account/${this.accountId}/webhooks`);
99
125
  }
100
126
  async updateWebhook(webhookId, request) {
101
- return this.request("PUT", `/webhook/${webhookId}`, request);
127
+ await this.ensureAuthenticated();
128
+ return this.request("PUT", `/api/v2/account/${this.accountId}/webhook/${webhookId}`, request);
102
129
  }
103
130
  async deleteWebhook(webhookId) {
104
- await this.request("DELETE", `/webhook/${webhookId}`);
131
+ await this.ensureAuthenticated();
132
+ await this.request("DELETE", `/api/v2/account/${this.accountId}/webhook/${webhookId}`);
105
133
  }
106
134
  // Reference Data
107
135
  async getFiatInstitutions(country) {
108
- return this.request("GET", `/fiat-institutions/${country}`);
136
+ await this.ensureAuthenticated();
137
+ return this.request("GET", `/api/v2/reference/fiat-institutions/${country}`);
109
138
  }
110
139
  }
package/dist/types.d.ts CHANGED
@@ -1,15 +1,24 @@
1
1
  export interface NeutronConfig {
2
2
  apiUrl: string;
3
+ apiKey: string;
4
+ apiSecret: string;
5
+ }
6
+ export interface AuthResponse {
3
7
  accountId: string;
4
- accessKey: string;
5
- secretKey: string;
8
+ accessToken: string;
9
+ refreshToken: string;
10
+ expiredAt: string;
11
+ scope: string;
6
12
  }
7
13
  export interface Account {
8
14
  id: string;
9
- name: string;
10
- email: string;
11
- status: string;
15
+ parentId?: string;
16
+ displayName: string;
17
+ accountStatus: string;
18
+ countryCode: string;
19
+ timezone: string;
12
20
  createdAt: string;
21
+ updatedAt: string;
13
22
  }
14
23
  export interface Wallet {
15
24
  id: string;
@@ -24,62 +33,49 @@ export interface ReceiveAddress {
24
33
  network?: string;
25
34
  expiresAt?: string;
26
35
  }
27
- export type TransactionMethod = "lightning" | "lightning_address" | "lnurl" | "bolt11" | "on_chain" | "eth" | "tron" | "bank" | "mobile_money" | "internal";
28
- export type TransactionStatus = "pending" | "processing" | "completed" | "failed" | "cancelled";
29
- export interface TransactionSource {
30
- method: TransactionMethod;
31
- currency: string;
32
- amount?: string;
33
- walletId?: string;
36
+ export type TransactionMethod = "lightning" | "lightning_address" | "lnurl" | "bolt11" | "on_chain" | "eth" | "tron" | "bank" | "mobile_money" | "vnd-instant" | "internal";
37
+ export type TransactionState = "quoted" | "pending" | "processing" | "completed" | "failed" | "cancelled";
38
+ export interface TransactionSourceReq {
39
+ ccy: string;
40
+ amtRequested?: number;
41
+ method: string;
42
+ notes?: string;
43
+ reqDetails?: Record<string, unknown>;
34
44
  }
35
- export interface TransactionDestination {
36
- method: TransactionMethod;
37
- currency: string;
38
- amount?: string;
39
- address?: string;
40
- lightningAddress?: string;
41
- bolt11?: string;
42
- accountNumber?: string;
43
- bankCode?: string;
44
- phoneNumber?: string;
45
- recipientName?: string;
46
- country?: string;
45
+ export interface TransactionDestReq {
46
+ ccy: string;
47
+ amtRequested?: number;
48
+ method: string;
49
+ reqDetails?: Record<string, unknown>;
50
+ kyc?: {
51
+ type: "individual" | "business";
52
+ details: Record<string, unknown>;
53
+ };
47
54
  }
48
55
  export interface CreateTransactionRequest {
49
- sourceReq: TransactionSource;
50
- destReq: TransactionDestination;
51
- reference?: string;
52
- metadata?: Record<string, unknown>;
56
+ extRefId?: string;
57
+ sourceReq: TransactionSourceReq;
58
+ destReq: TransactionDestReq;
59
+ sourceOfFunds?: {
60
+ purpose?: number;
61
+ source?: number;
62
+ relationship?: number;
63
+ };
53
64
  }
54
65
  export interface Transaction {
55
- id: string;
56
- reference: string;
57
- status: TransactionStatus;
58
- source: {
59
- method: TransactionMethod;
60
- currency: string;
61
- amount: string;
62
- };
63
- destination: {
64
- method: TransactionMethod;
65
- currency: string;
66
- amount: string;
67
- address?: string;
68
- };
69
- fees: {
70
- amount: string;
71
- currency: string;
72
- };
73
- exchangeRate?: string;
74
- paymentRequest?: string;
75
- createdAt: string;
76
- updatedAt: string;
66
+ txnId: string;
67
+ extRefId?: string;
68
+ txnState: TransactionState;
69
+ fxRate?: number;
70
+ sourceReq: TransactionSourceReq;
71
+ destReq: TransactionDestReq;
72
+ createdAt?: string;
73
+ updatedAt?: string;
77
74
  completedAt?: string;
78
- metadata?: Record<string, unknown>;
79
75
  }
80
76
  export interface TransactionListParams {
81
- status?: TransactionStatus;
82
- method?: TransactionMethod;
77
+ status?: TransactionState;
78
+ method?: string;
83
79
  currency?: string;
84
80
  fromDate?: string;
85
81
  toDate?: string;
@@ -97,7 +93,7 @@ export interface Webhook {
97
93
  id: string;
98
94
  url: string;
99
95
  events: WebhookEvent[];
100
- secret: string;
96
+ secret?: string;
101
97
  status: "active" | "inactive";
102
98
  createdAt: string;
103
99
  }
@@ -117,11 +113,3 @@ export interface FiatInstitution {
117
113
  type: "bank" | "mobile_money";
118
114
  supportedCurrencies: string[];
119
115
  }
120
- export interface ApiResponse<T> {
121
- success: boolean;
122
- data?: T;
123
- error?: {
124
- code: string;
125
- message: string;
126
- };
127
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neutron-mcp",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "MCP server for Neutron - Lightning payments, Bitcoin, USDT, and fiat transactions for AI-powered applications",
5
5
  "main": "dist/index.js",
6
6
  "bin": {