Inspect provisioned accounts and submit idempotent, independently approved transactions
Provision the signer outside MCP and expose only its owner-only file to the server:
NEO_ENABLE_WRITES=true NEO_SIGNER_WIF_FILE=/run/secrets/neo-signer-wif NEO_WRITE_STATE_DIR=/var/lib/neo-n3-mcp/write-operations # The signer file is created out of band, owned by the server user, mode 0600.
MCP exposes sanitized metadata for wallets provisioned outside the model-facing channel:
const wallet = await tools.get_wallet({
address: accountAddress
});
console.log(wallet.address, wallet.publicKey);
Read sanitized local metadata, on-chain NEP-17 balances, and claimable GAS:
const address = "NZNos2WqTbu5oCgyfss9kUJgBXJqhuYAaj";
// This returns metadata only; encrypted key material is omitted.
const localWallet = await tools.get_wallet({ address });
const balance = await tools.get_balance({
address,
network: "testnet"
});
const claimableGas = await tools.get_unclaimed_gas({
address,
network: "testnet"
});
console.log({ localWallet, balance, claimableGas });
Estimate fees first, then send a NEP-17 asset with explicit confirmation:
const NEO_HASH = "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5";
const fromAddress = "NZNos2WqTbu5oCgyfss9kUJgBXJqhuYAaj";
const toAddress = "NYjzhdekseMYWvYpSoAeypqMiwMuEUDhKB";
const fees = await tools.estimate_transfer_fees({
fromAddress,
toAddress,
asset: NEO_HASH,
amount: "1",
network: "testnet"
});
console.log("Exact fees (datos):", fees.networkFeeDatos, fees.systemFeeDatos);
console.log("Formatted fees (GAS):", fees.networkFeeGas, fees.systemFeeGas);
const transfer = await tools.transfer_assets({
idempotencyKey: "transfer-2026-07-11-001",
toAddress,
asset: NEO_HASH,
amount: "1",
network: "testnet"
});
console.log("Submitted transaction:", transfer.txid);
Query NEP-17 transfers plus NEP-11 balances and transfer history:
const address = "NZNos2WqTbu5oCgyfss9kUJgBXJqhuYAaj";
const fromTimestampMs = Date.now() - (30 * 24 * 60 * 60 * 1000);
const nep17Transfers = await tools.get_nep17_transfers({
address,
fromTimestampMs,
network: "testnet"
});
const nep11Balances = await tools.get_nep11_balances({
address,
network: "testnet"
});
const nep11Transfers = await tools.get_nep11_transfers({
address,
fromTimestampMs,
toTimestampMs: Date.now(),
network: "testnet"
});
console.log({ nep17Transfers, nep11Balances, nep11Transfers });
Claiming GAS uses the configured signer, durable idempotency, and exact elicited approval:
const claim = await tools.claim_gas({
idempotencyKey: "gas-claim-2026-07-11-001",
network: "testnet"
});
const receipt = await tools.wait_for_transaction({
txid: claim.txid,
timeoutMs: 120000,
pollIntervalMs: 3000,
includeApplicationLog: true,
network: "testnet"
});
console.log("Claim receipt:", receipt);
A compact helper that estimates, confirms, submits, and waits for a transfer:
async function transferAndWait(tools, request) {
const fees = await tools.estimate_transfer_fees({
fromAddress: request.fromAddress,
toAddress: request.toAddress,
asset: request.asset,
amount: request.amount,
network: request.network
});
// Present fees and destination to the user before reaching this call.
const transfer = await tools.transfer_assets({
idempotencyKey: request.idempotencyKey,
toAddress: request.toAddress,
asset: request.asset,
amount: request.amount,
network: request.network
});
const receipt = await tools.wait_for_transaction({
txid: transfer.txid,
timeoutMs: 120000,
pollIntervalMs: 3000,
network: request.network
});
return { fees, txid: transfer.txid, receipt };
}
const result = await transferAndWait(tools, {
idempotencyKey: "transfer-2026-07-11-002",
fromAddress: "NZNos2WqTbu5oCgyfss9kUJgBXJqhuYAaj",
toAddress: "NYjzhdekseMYWvYpSoAeypqMiwMuEUDhKB",
asset: "0xd2a4cff31913016155e38e474a2c06d08be276cf",
amount: "0.5",
network: "testnet"
});
console.log("Confirmed transfer:", result);