@goplausible/algorand-mcp 4.2.3 → 4.2.4
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 +21 -22
- package/dist/tools/algodManager.js +2 -2
- package/dist/tools/apiManager/index.d.ts +1 -1
- package/dist/tools/apiManager/indexer/account.js +76 -69
- package/dist/tools/apiManager/indexer/application.js +72 -65
- package/dist/tools/apiManager/indexer/asset.js +22 -19
- package/dist/tools/arc26Manager.d.ts +0 -5
- package/dist/tools/arc26Manager.js +64 -65
- package/dist/tools/utilityManager.js +1 -1
- package/dist/tools/walletManager.js +2 -3
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -369,8 +369,8 @@ See [Secure Wallet](#secure-wallet) for full architecture details.
|
|
|
369
369
|
| `wallet_remove_account` | Remove an account from the wallet by nickname or index |
|
|
370
370
|
| `wallet_list_accounts` | List all accounts with nicknames, addresses, and limits |
|
|
371
371
|
| `wallet_switch_account` | Switch the active account by nickname or index |
|
|
372
|
-
| `wallet_get_info` | Get active account
|
|
373
|
-
| `wallet_get_assets` | Get all
|
|
372
|
+
| `wallet_get_info` | Get info for the **active account this MCP server owns** (keychain-backed): address, public key, balance, opted-in counts, plus wallet-only fields (allowance, daily allowance, daily spent). For arbitrary on-chain accounts use `api_algod_get_account_info`. |
|
|
373
|
+
| `wallet_get_assets` | Get all ASA holdings for the **active account this MCP server owns**. For arbitrary on-chain accounts use `api_algod_get_account_info` or `api_algod_get_account_asset_info`. |
|
|
374
374
|
| `wallet_sign_transaction` | Sign a single transaction with the active account (enforces spending limits) |
|
|
375
375
|
| `wallet_sign_transaction_group` | Sign a group of transactions with the active account (auto-assigns group ID) |
|
|
376
376
|
| `wallet_sign_data` | Sign arbitrary hex data with raw Ed25519 (noble, no SDK prefix) |
|
|
@@ -437,11 +437,13 @@ See [Secure Wallet](#secure-wallet) for full architecture details.
|
|
|
437
437
|
| `compile_teal` | Compile TEAL source code |
|
|
438
438
|
| `disassemble_teal` | Disassemble TEAL bytecode to source |
|
|
439
439
|
| `send_raw_transaction` | Submit signed transactions to the network |
|
|
440
|
-
| `simulate_raw_transactions` | Simulate
|
|
441
|
-
| `simulate_transactions` | Simulate
|
|
440
|
+
| `simulate_raw_transactions` | Simulate already-encoded transactions (base64 bytes). Pass/fail + log/cost only — no trace, no extra budget. |
|
|
441
|
+
| `simulate_transactions` | Simulate decoded transaction groups with full `SimulateRequest` config (trace, extra opcode budget, unnamed-resource handling, unsigned txns). |
|
|
442
442
|
|
|
443
443
|
### Algod API Tools (13 tools)
|
|
444
444
|
|
|
445
|
+
Live, current-state reads against an Algod node. **Default choice for account/application/asset lookups** — the matching indexer endpoints were intentionally disabled to keep the tool surface lean (see [.notes/redundant-tools-report.md](.notes/redundant-tools-report.md)). Use the indexer family below only when you need historical or filtered queries that algod cannot serve.
|
|
446
|
+
|
|
445
447
|
| Tool | Description |
|
|
446
448
|
|---|---|
|
|
447
449
|
| `api_algod_get_account_info` | Get account balance, assets, and auth address |
|
|
@@ -458,27 +460,24 @@ See [Secure Wallet](#secure-wallet) for full architecture details.
|
|
|
458
460
|
| `api_algod_get_node_status` | Get current node status |
|
|
459
461
|
| `api_algod_get_node_status_after_block` | Get node status after a specific round |
|
|
460
462
|
|
|
461
|
-
### Indexer API Tools (
|
|
463
|
+
### Indexer API Tools (10 tools)
|
|
464
|
+
|
|
465
|
+
Historical / filtered queries against an Algorand Indexer instance. Use these for time-range scans, paginated searches, log retrieval, and creator/holder discovery — anything algod's current-state endpoints cannot answer.
|
|
466
|
+
|
|
467
|
+
Seven indexer endpoints that duplicated algod equivalents (account-by-id, account assets, account app local states, application by id, application box, application boxes, asset by id) were intentionally disabled. They live commented-out in [src/tools/apiManager/indexer/](src/tools/apiManager/indexer/) and can be re-enabled in one place if needed.
|
|
462
468
|
|
|
463
469
|
| Tool | Description |
|
|
464
470
|
|---|---|
|
|
465
|
-
| `api_indexer_lookup_account_by_id` | Get account information |
|
|
466
|
-
| `api_indexer_lookup_account_assets` | Get account assets |
|
|
467
|
-
| `api_indexer_lookup_account_app_local_states` | Get account app local states |
|
|
468
471
|
| `api_indexer_lookup_account_created_applications` | Get apps created by account |
|
|
469
|
-
| `api_indexer_search_for_accounts` | Search accounts with filters |
|
|
470
|
-
| `
|
|
471
|
-
| `
|
|
472
|
-
| `
|
|
473
|
-
| `
|
|
474
|
-
| `
|
|
475
|
-
| `
|
|
476
|
-
| `
|
|
477
|
-
| `
|
|
478
|
-
| `api_indexer_search_for_assets` | Search assets |
|
|
479
|
-
| `api_indexer_lookup_transaction_by_id` | Get transaction by ID |
|
|
480
|
-
| `api_indexer_lookup_account_transactions` | Get account transaction history |
|
|
481
|
-
| `api_indexer_search_for_transactions` | Search transactions |
|
|
472
|
+
| `api_indexer_search_for_accounts` | Search accounts with filters (asset/app holdings, balance ranges) |
|
|
473
|
+
| `api_indexer_lookup_application_logs` | Get application log messages over a round range |
|
|
474
|
+
| `api_indexer_search_for_applications` | Search applications by creator |
|
|
475
|
+
| `api_indexer_lookup_asset_balances` | Get all accounts holding an asset with their balances |
|
|
476
|
+
| `api_indexer_lookup_asset_transactions` | Get transactions involving an asset (time/round/address-role filters) |
|
|
477
|
+
| `api_indexer_search_for_assets` | Search assets by creator, name, or unit |
|
|
478
|
+
| `api_indexer_lookup_transaction_by_id` | Get a confirmed transaction by ID |
|
|
479
|
+
| `api_indexer_lookup_account_transactions` | Get an account's transaction history (time/round/type/asset filters) |
|
|
480
|
+
| `api_indexer_search_for_transactions` | Search transactions across the chain with filters |
|
|
482
481
|
|
|
483
482
|
### NFDomains Tools (6 tools)
|
|
484
483
|
|
|
@@ -701,7 +700,7 @@ npm test
|
|
|
701
700
|
| `transactionManager` | Payment, asset, app transaction building; sign_transaction; assign_group_id |
|
|
702
701
|
| `algodManager` | TEAL compile/disassemble, send raw, simulate |
|
|
703
702
|
| `apiAlgod` | All 13 algod API tools with correct mock routing |
|
|
704
|
-
| `apiIndexer` | All
|
|
703
|
+
| `apiIndexer` | All 10 active indexer API tools with fluent builder mocks |
|
|
705
704
|
| `apiNfd` | NFD get/search/browse with mocked fetch |
|
|
706
705
|
| `apiTinyman` | Tinyman pool/swap with error handling |
|
|
707
706
|
| `arc26Manager` | ARC-26 URI generation and QR code SVG output |
|
|
@@ -246,12 +246,12 @@ AlgodManager.algodTools = [
|
|
|
246
246
|
},
|
|
247
247
|
{
|
|
248
248
|
name: 'simulate_raw_transactions',
|
|
249
|
-
description: 'Simulate raw
|
|
249
|
+
description: 'Simulate already-encoded, optionally-signed transactions (base64 bytes). Use this when you have raw txn bytes ready and only need a pass/fail + log/cost result — no execution tracing, no extra opcode budget, no unnamed-resource handling. For a richer simulation (trace, extra budget, unsigned txns, multiple groups), use simulate_transactions.',
|
|
250
250
|
inputSchema: withCommonParams(algodToolSchemas.simulateRawTransactions),
|
|
251
251
|
},
|
|
252
252
|
{
|
|
253
253
|
name: 'simulate_transactions',
|
|
254
|
-
description: 'Simulate
|
|
254
|
+
description: 'Simulate one or more transaction groups built from decoded transaction objects, with a full SimulateRequest config (allowEmptySignatures, allowMoreLogging, allowUnnamedResources, execTraceConfig, extraOpcodeBudget, round). Use this when you need execution traces, extra opcode budget, to simulate unsigned txns, or to opt into Algorand v9+ simulate features. For a quick pass/fail check on pre-encoded bytes, use simulate_raw_transactions instead.',
|
|
255
255
|
inputSchema: withCommonParams(algodToolSchemas.simulateTransactions),
|
|
256
256
|
}
|
|
257
257
|
];
|
|
@@ -38,7 +38,7 @@ export declare const apiManager: ({
|
|
|
38
38
|
src: string;
|
|
39
39
|
mimeType?: string | undefined;
|
|
40
40
|
sizes?: string[] | undefined;
|
|
41
|
-
theme?: "
|
|
41
|
+
theme?: "light" | "dark" | undefined;
|
|
42
42
|
}[] | undefined;
|
|
43
43
|
title?: string | undefined;
|
|
44
44
|
})[];
|
|
@@ -3,60 +3,64 @@ import { getIndexerClient, extractNetwork } from '../../../algorand-client.js';
|
|
|
3
3
|
import { ResponseProcessor } from '../../../utils/responseProcessor.js';
|
|
4
4
|
import { withCommonParams } from '../../commonParams.js';
|
|
5
5
|
export const accountTools = [
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
6
|
+
// Disabled: redundant with api_algod_get_account_info (live algod variant covers the same query).
|
|
7
|
+
// See .notes/redundant-tools-report.md §1.
|
|
8
|
+
// {
|
|
9
|
+
// name: 'api_indexer_lookup_account_by_id',
|
|
10
|
+
// description: 'Get account information from indexer',
|
|
11
|
+
// inputSchema: withCommonParams({
|
|
12
|
+
// type: 'object',
|
|
13
|
+
// properties: {
|
|
14
|
+
// address: {
|
|
15
|
+
// type: 'string',
|
|
16
|
+
// description: 'Account address'
|
|
17
|
+
// }
|
|
18
|
+
// },
|
|
19
|
+
// required: ['address']
|
|
20
|
+
// })
|
|
21
|
+
// },
|
|
22
|
+
// Disabled: redundant with api_algod_get_account_asset_info.
|
|
23
|
+
// {
|
|
24
|
+
// name: 'api_indexer_lookup_account_assets',
|
|
25
|
+
// description: 'Get account assets',
|
|
26
|
+
// inputSchema: withCommonParams({
|
|
27
|
+
// type: 'object',
|
|
28
|
+
// properties: {
|
|
29
|
+
// address: {
|
|
30
|
+
// type: 'string',
|
|
31
|
+
// description: 'Account address'
|
|
32
|
+
// },
|
|
33
|
+
// limit: {
|
|
34
|
+
// type: 'integer',
|
|
35
|
+
// description: 'Maximum number of assets to return'
|
|
36
|
+
// },
|
|
37
|
+
// assetId: {
|
|
38
|
+
// type: 'integer',
|
|
39
|
+
// description: 'Filter by asset ID'
|
|
40
|
+
// },
|
|
41
|
+
// nextToken: {
|
|
42
|
+
// type: 'string',
|
|
43
|
+
// description: 'Token for retrieving the next page of results'
|
|
44
|
+
// }
|
|
45
|
+
// },
|
|
46
|
+
// required: ['address']
|
|
47
|
+
// })
|
|
48
|
+
// },
|
|
49
|
+
// Disabled: redundant with api_algod_get_account_application_info.
|
|
50
|
+
// {
|
|
51
|
+
// name: 'api_indexer_lookup_account_app_local_states',
|
|
52
|
+
// description: 'Get account application local states',
|
|
53
|
+
// inputSchema: withCommonParams({
|
|
54
|
+
// type: 'object',
|
|
55
|
+
// properties: {
|
|
56
|
+
// address: {
|
|
57
|
+
// type: 'string',
|
|
58
|
+
// description: 'Account address'
|
|
59
|
+
// }
|
|
60
|
+
// },
|
|
61
|
+
// required: ['address']
|
|
62
|
+
// })
|
|
63
|
+
// },
|
|
60
64
|
{
|
|
61
65
|
name: 'api_indexer_lookup_account_created_applications',
|
|
62
66
|
description: 'Get applications created by this account',
|
|
@@ -218,16 +222,18 @@ export const handleAccountTools = ResponseProcessor.wrapResourceHandler(async fu
|
|
|
218
222
|
const name = args.name;
|
|
219
223
|
const network = extractNetwork(args);
|
|
220
224
|
switch (name) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
225
|
+
// Disabled: redundant with api_algod_get_account_info. See .notes/redundant-tools-report.md §1.
|
|
226
|
+
// case 'api_indexer_lookup_account_by_id': {
|
|
227
|
+
// const { address } = args;
|
|
228
|
+
// const info = await lookupAccountByID(address, network);
|
|
229
|
+
// return info;
|
|
230
|
+
// }
|
|
231
|
+
// Disabled: redundant with api_algod_get_account_application_info.
|
|
232
|
+
// case 'api_indexer_lookup_account_app_local_states': {
|
|
233
|
+
// const { address } = args;
|
|
234
|
+
// const info = await lookupAccountAppLocalStates(address, network);
|
|
235
|
+
// return info;
|
|
236
|
+
// }
|
|
231
237
|
case 'api_indexer_lookup_account_created_applications': {
|
|
232
238
|
const { address } = args;
|
|
233
239
|
const info = await lookupAccountCreatedApplications(address, network);
|
|
@@ -237,11 +243,12 @@ export const handleAccountTools = ResponseProcessor.wrapResourceHandler(async fu
|
|
|
237
243
|
const info = await searchAccounts(args, network);
|
|
238
244
|
return info.accounts;
|
|
239
245
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
246
|
+
// Disabled: redundant with api_algod_get_account_asset_info.
|
|
247
|
+
// case 'api_indexer_lookup_account_assets': {
|
|
248
|
+
// const { address, ...params } = args;
|
|
249
|
+
// const info = await lookupAccountAssets(address, params, network);
|
|
250
|
+
// return info.assets;
|
|
251
|
+
// }
|
|
245
252
|
default:
|
|
246
253
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
247
254
|
}
|
|
@@ -4,20 +4,22 @@ import { ResponseProcessor } from '../../../utils/responseProcessor.js';
|
|
|
4
4
|
import { withCommonParams } from '../../commonParams.js';
|
|
5
5
|
import algosdk from 'algosdk';
|
|
6
6
|
export const applicationTools = [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
7
|
+
// Disabled: redundant with api_algod_get_application_by_id (live algod variant covers the same query).
|
|
8
|
+
// See .notes/redundant-tools-report.md §1.
|
|
9
|
+
// {
|
|
10
|
+
// name: 'api_indexer_lookup_applications',
|
|
11
|
+
// description: 'Get application information from indexer',
|
|
12
|
+
// inputSchema: withCommonParams({
|
|
13
|
+
// type: 'object',
|
|
14
|
+
// properties: {
|
|
15
|
+
// appId: {
|
|
16
|
+
// type: 'integer',
|
|
17
|
+
// description: 'Application ID'
|
|
18
|
+
// }
|
|
19
|
+
// },
|
|
20
|
+
// required: ['appId']
|
|
21
|
+
// })
|
|
22
|
+
// },
|
|
21
23
|
{
|
|
22
24
|
name: 'api_indexer_lookup_application_logs',
|
|
23
25
|
description: 'Get application log messages',
|
|
@@ -77,42 +79,44 @@ export const applicationTools = [
|
|
|
77
79
|
}
|
|
78
80
|
})
|
|
79
81
|
},
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
82
|
+
// Disabled: redundant with api_algod_get_application_box.
|
|
83
|
+
// {
|
|
84
|
+
// name: 'api_indexer_lookup_application_box',
|
|
85
|
+
// description: 'Get application box by name',
|
|
86
|
+
// inputSchema: withCommonParams({
|
|
87
|
+
// type: 'object',
|
|
88
|
+
// properties: {
|
|
89
|
+
// appId: {
|
|
90
|
+
// type: 'integer',
|
|
91
|
+
// description: 'Application ID'
|
|
92
|
+
// },
|
|
93
|
+
// boxName: {
|
|
94
|
+
// type: 'string',
|
|
95
|
+
// description: 'Box name Buffer'
|
|
96
|
+
// }
|
|
97
|
+
// },
|
|
98
|
+
// required: ['appId', 'boxName']
|
|
99
|
+
// })
|
|
100
|
+
// },
|
|
101
|
+
// Disabled: redundant with api_algod_get_application_boxes.
|
|
102
|
+
// {
|
|
103
|
+
// name: 'api_indexer_lookup_application_boxes',
|
|
104
|
+
// description: 'Get all application boxes',
|
|
105
|
+
// inputSchema: withCommonParams({
|
|
106
|
+
// type: 'object',
|
|
107
|
+
// properties: {
|
|
108
|
+
// appId: {
|
|
109
|
+
// type: 'integer',
|
|
110
|
+
// description: 'Application ID'
|
|
111
|
+
// },
|
|
112
|
+
// maxBoxes: {
|
|
113
|
+
// type: 'integer',
|
|
114
|
+
// description: 'Maximum number of boxes to return'
|
|
115
|
+
// }
|
|
116
|
+
// },
|
|
117
|
+
// required: ['appId']
|
|
118
|
+
// })
|
|
119
|
+
// }
|
|
116
120
|
];
|
|
117
121
|
export async function lookupApplications(appId, network = 'mainnet') {
|
|
118
122
|
try {
|
|
@@ -260,11 +264,12 @@ export const handleApplicationTools = ResponseProcessor.wrapResourceHandler(asyn
|
|
|
260
264
|
const name = args.name;
|
|
261
265
|
const network = extractNetwork(args);
|
|
262
266
|
switch (name) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
267
|
+
// Disabled: redundant with api_algod_get_application_by_id. See .notes/redundant-tools-report.md §1.
|
|
268
|
+
// case 'api_indexer_lookup_applications': {
|
|
269
|
+
// const { appId } = args;
|
|
270
|
+
// const info = await lookupApplications(appId, network);
|
|
271
|
+
// return info.application;
|
|
272
|
+
// }
|
|
268
273
|
case 'api_indexer_lookup_application_logs': {
|
|
269
274
|
const { appId, ...params } = args;
|
|
270
275
|
const logs = await lookupApplicationLogs(appId, params, network);
|
|
@@ -274,16 +279,18 @@ export const handleApplicationTools = ResponseProcessor.wrapResourceHandler(asyn
|
|
|
274
279
|
const info = await searchForApplications(args, network);
|
|
275
280
|
return info.applications;
|
|
276
281
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
282
|
+
// Disabled: redundant with api_algod_get_application_box.
|
|
283
|
+
// case 'api_indexer_lookup_application_box': {
|
|
284
|
+
// const { appId, boxName } = args;
|
|
285
|
+
// const box = await lookupApplicationBoxByIDandName(appId, boxName, network);
|
|
286
|
+
// return box;
|
|
287
|
+
// }
|
|
288
|
+
// Disabled: redundant with api_algod_get_application_boxes.
|
|
289
|
+
// case 'api_indexer_lookup_application_boxes': {
|
|
290
|
+
// const { appId, maxBoxes } = args;
|
|
291
|
+
// const boxes = await searchForApplicationBoxes(appId, maxBoxes, network);
|
|
292
|
+
// return boxes.boxes;
|
|
293
|
+
// }
|
|
287
294
|
default:
|
|
288
295
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
289
296
|
}
|
|
@@ -3,20 +3,22 @@ import { getIndexerClient, extractNetwork } from '../../../algorand-client.js';
|
|
|
3
3
|
import { ResponseProcessor } from '../../../utils/responseProcessor.js';
|
|
4
4
|
import { withCommonParams } from '../../commonParams.js';
|
|
5
5
|
export const assetTools = [
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
6
|
+
// Disabled: redundant with api_algod_get_asset_by_id (live algod variant covers the same query).
|
|
7
|
+
// See .notes/redundant-tools-report.md §1.
|
|
8
|
+
// {
|
|
9
|
+
// name: 'api_indexer_lookup_asset_by_id',
|
|
10
|
+
// description: 'Get asset information and configuration',
|
|
11
|
+
// inputSchema: withCommonParams({
|
|
12
|
+
// type: 'object',
|
|
13
|
+
// properties: {
|
|
14
|
+
// assetId: {
|
|
15
|
+
// type: 'integer',
|
|
16
|
+
// description: 'Asset ID'
|
|
17
|
+
// }
|
|
18
|
+
// },
|
|
19
|
+
// required: ['assetId']
|
|
20
|
+
// })
|
|
21
|
+
// },
|
|
20
22
|
{
|
|
21
23
|
name: 'api_indexer_lookup_asset_balances',
|
|
22
24
|
description: 'Get accounts holding this asset and their balances',
|
|
@@ -267,11 +269,12 @@ export const handleAssetTools = ResponseProcessor.wrapResourceHandler(async func
|
|
|
267
269
|
const name = args.name;
|
|
268
270
|
const network = extractNetwork(args);
|
|
269
271
|
switch (name) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
272
|
+
// Disabled: redundant with api_algod_get_asset_by_id. See .notes/redundant-tools-report.md §1.
|
|
273
|
+
// case 'api_indexer_lookup_asset_by_id': {
|
|
274
|
+
// const { assetId } = args;
|
|
275
|
+
// const info = await lookupAssetByID(assetId, network);
|
|
276
|
+
// return info.asset;
|
|
277
|
+
// }
|
|
275
278
|
case 'api_indexer_lookup_asset_balances': {
|
|
276
279
|
const { assetId, ...params } = args;
|
|
277
280
|
const balances = await lookupAssetBalances(assetId, params, network);
|
|
@@ -17,11 +17,6 @@ export declare class Arc26Manager {
|
|
|
17
17
|
* @param params The parameters for constructing the URI
|
|
18
18
|
* @returns Object containing the URI and QR code as base64 data URL
|
|
19
19
|
*/
|
|
20
|
-
generateUriAndQr(params: Arc26ToolInput): Promise<{
|
|
21
|
-
uri: string;
|
|
22
|
-
qrCodePng: string;
|
|
23
|
-
qrCodeUtf8: string;
|
|
24
|
-
}>;
|
|
25
20
|
/**
|
|
26
21
|
* Constructs an Algorand URI according to ARC-26 specification and generates a QR code
|
|
27
22
|
* @param params The parameters for constructing the URI
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as QRCode from 'qrcode';
|
|
2
1
|
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
|
|
3
2
|
import { withCommonParams } from './commonParams.js';
|
|
4
3
|
export class Arc26Manager {
|
|
@@ -50,70 +49,70 @@ export class Arc26Manager {
|
|
|
50
49
|
* @param params The parameters for constructing the URI
|
|
51
50
|
* @returns Object containing the URI and QR code as base64 data URL
|
|
52
51
|
*/
|
|
53
|
-
async generateUriAndQr(params) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
52
|
+
// async generateUriAndQr(params: Arc26ToolInput): Promise<{ uri: string; qrCodePng: string; qrCodeUtf8: string }> {
|
|
53
|
+
// // Validate address format (base32 string)
|
|
54
|
+
// if (!params.address || !/^[A-Z2-7]{58}$/.test(params.address)) {
|
|
55
|
+
// throw new McpError(ErrorCode.InvalidParams, 'Invalid Algorand address format');
|
|
56
|
+
// }
|
|
57
|
+
// // Start building the URI with the scheme and address
|
|
58
|
+
// let uri = `algorand://${params.address}`;
|
|
59
|
+
// // Build query parameters
|
|
60
|
+
// const queryParams: string[] = [];
|
|
61
|
+
// // Add optional parameters if provided
|
|
62
|
+
// if (params.label) {
|
|
63
|
+
// queryParams.push(`label=${encodeURIComponent(params.label)}`);
|
|
64
|
+
// }
|
|
65
|
+
// if (typeof params.amount === 'number') {
|
|
66
|
+
// if (params.amount < 0) {
|
|
67
|
+
// throw new McpError(ErrorCode.InvalidParams, 'Amount must be non-negative');
|
|
68
|
+
// }
|
|
69
|
+
// // Convert to microAlgos and ensure no decimals
|
|
70
|
+
// const microAlgos = Math.floor(params.amount);
|
|
71
|
+
// queryParams.push(`amount=${microAlgos}`);
|
|
72
|
+
// }
|
|
73
|
+
// if (typeof params.asset === 'number') {
|
|
74
|
+
// if (params.asset < 0) {
|
|
75
|
+
// throw new McpError(ErrorCode.InvalidParams, 'Asset ID must be non-negative');
|
|
76
|
+
// }
|
|
77
|
+
// queryParams.push(`asset=${params.asset}`);
|
|
78
|
+
// }
|
|
79
|
+
// if (params.note) {
|
|
80
|
+
// queryParams.push(`note=${encodeURIComponent(params.note)}`);
|
|
81
|
+
// }
|
|
82
|
+
// if (params.xnote) {
|
|
83
|
+
// queryParams.push(`xnote=${encodeURIComponent(params.xnote)}`);
|
|
84
|
+
// }
|
|
85
|
+
// // Add query parameters to URI if any exist
|
|
86
|
+
// if (queryParams.length > 0) {
|
|
87
|
+
// uri += '?' + queryParams.join('&');
|
|
88
|
+
// }
|
|
89
|
+
// // Generate QR code as SVG
|
|
90
|
+
// const qrCodeUtf8Raw = await QRCode.toString(uri, {
|
|
91
|
+
// type: 'utf8',
|
|
92
|
+
// errorCorrectionLevel: 'H',
|
|
93
|
+
// // margin: 1,
|
|
94
|
+
// width: 128
|
|
95
|
+
// });
|
|
96
|
+
// // Invert for better terminal contrast
|
|
97
|
+
// const qrCodeUtf8 = qrCodeUtf8Raw
|
|
98
|
+
// .replace(/█/g, '⬜').replace(/ /g, '█').replace(/⬜/g, ' ')
|
|
99
|
+
// .replace(/▀/g, '⬛').replace(/▄/g, '▀').replace(/⬛/g, '▄');
|
|
100
|
+
// const qrCodePng = await QRCode.toDataURL(uri, {
|
|
101
|
+
// type: 'image/png',
|
|
102
|
+
// errorCorrectionLevel: 'H',
|
|
103
|
+
// color: {
|
|
104
|
+
// dark: '#000000',
|
|
105
|
+
// light: '#FFFFFF'
|
|
106
|
+
// },
|
|
107
|
+
// margin: 4,
|
|
108
|
+
// width: 128
|
|
109
|
+
// });
|
|
110
|
+
// return {
|
|
111
|
+
// uri,
|
|
112
|
+
// qrCodePng: qrCodePng,
|
|
113
|
+
// qrCodeUtf8: qrCodeUtf8
|
|
114
|
+
// };
|
|
115
|
+
// }
|
|
117
116
|
/**
|
|
118
117
|
* Constructs an Algorand URI according to ARC-26 specification and generates a QR code
|
|
119
118
|
* @param params The parameters for constructing the URI
|
|
@@ -86,7 +86,7 @@ export class UtilityManager {
|
|
|
86
86
|
type: 'text',
|
|
87
87
|
text: JSON.stringify({
|
|
88
88
|
name: 'Algorand MCP Server',
|
|
89
|
-
version: '4.2.
|
|
89
|
+
version: '4.2.4',
|
|
90
90
|
builder: 'GoPlausible',
|
|
91
91
|
description: 'A Model Context Protocol (MCP) server providing comprehensive access to the Algorand blockchain. Supports account management, transaction building and signing, smart contract interaction, asset operations, ARC-26 URI generation, and deep integration with Algorand ecosystem services including NFDomains, Tinyman, Vestige, and Ultrade.',
|
|
92
92
|
blockchain: 'Algorand — a carbon-negative, pure proof-of-stake Layer 1 blockchain delivering instant finality, low fees, and advanced smart contract capabilities via AVM (Algorand Virtual Machine).',
|
|
@@ -67,7 +67,6 @@ const walletToolSchemas = {
|
|
|
67
67
|
addAccount: {
|
|
68
68
|
type: 'object',
|
|
69
69
|
properties: {
|
|
70
|
-
mnemonic: { type: 'string', description: '25-word mnemonic to import. If omitted, a new account is generated.' },
|
|
71
70
|
nickname: { type: 'string', description: 'Human-readable nickname for this account' },
|
|
72
71
|
allowance: { type: 'number', description: 'Max per-transaction amount in microAlgos (0 = unlimited)' },
|
|
73
72
|
dailyAllowance: { type: 'number', description: 'Max daily spending total in microAlgos (0 = unlimited)' }
|
|
@@ -767,12 +766,12 @@ WalletManager.walletTools = [
|
|
|
767
766
|
},
|
|
768
767
|
{
|
|
769
768
|
name: 'wallet_get_info',
|
|
770
|
-
description: 'Get the
|
|
769
|
+
description: 'Get info for the ACTIVE wallet account (an account whose private key this MCP server owns in the OS keychain). Returns nickname, address, public key, network, on-chain balance, min-balance, opted-in apps/assets counts, plus wallet-only fields: per-tx allowance, daily allowance, and daily-spent counter. Use this when you want to know the state of "the wallet you control." For an arbitrary on-chain account that this wallet does NOT own, use api_algod_get_account_info instead.',
|
|
771
770
|
inputSchema: withCommonParams(walletToolSchemas.getInfo),
|
|
772
771
|
},
|
|
773
772
|
{
|
|
774
773
|
name: 'wallet_get_assets',
|
|
775
|
-
description: 'Get all
|
|
774
|
+
description: 'Get all ASA holdings for the ACTIVE wallet account (an account whose private key this MCP server owns). Returns the wallet nickname, address, network, and the assets array. Use this when listing holdings of "the wallet you control." For asset holdings of an arbitrary on-chain account, use api_algod_get_account_info (returns full account including assets) or api_algod_get_account_asset_info (single asset).',
|
|
776
775
|
inputSchema: withCommonParams(walletToolSchemas.getAssets),
|
|
777
776
|
},
|
|
778
777
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goplausible/algorand-mcp",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.4",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"test:e2e": "NODE_OPTIONS='--experimental-vm-modules' jest --config tests/jest.config.e2e.js",
|
|
14
14
|
"test:all": "npm test && npm run test:e2e",
|
|
15
15
|
"typecheck": "tsc --noEmit",
|
|
16
|
+
"tag": "git tag v$npm_package_version && git push origin v$npm_package_version",
|
|
17
|
+
"retag": "git tag -f v$npm_package_version && git push -f origin v$npm_package_version",
|
|
18
|
+
"publish:npm": "npm publish",
|
|
16
19
|
"prepublishOnly": "npm run clean && npm run build"
|
|
17
20
|
},
|
|
18
21
|
"keywords": [
|