Agent-facing strings: AP3X terminology, working Koios default, vocabulary cleanup

- ADA -> AP3X in tool/param descriptions, outputs, and safety messages
- default testnet Koios URL -> v2 endpoint (old default returns 503)
- self-improvement descriptions: improvement proposals / proposal metrics
- em dashes -> hyphens in strings and comments

No logic changes; code identifiers and protocol field names untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
FilipBl4gojevic
2026-07-27 12:47:49 +02:00
parent 8e0d381a7f
commit 3d34ae41c8
7 changed files with 97 additions and 97 deletions

View File

@@ -3,7 +3,7 @@
# Vector Network Endpoints
VECTOR_OGMIOS_URL=https://ogmios.vector.testnet.apexfusion.org
VECTOR_KOIOS_URL=https://koios.vector.testnet.apexfusion.org/
VECTOR_KOIOS_URL=https://v2.koios.vector.testnet.apexfusion.org/
VECTOR_SUBMIT_URL=https://submit.vector.testnet.apexfusion.org/api/submit/tx
VECTOR_EXPLORER_URL=https://vector.testnet.apexscan.org

View File

@@ -13,14 +13,14 @@ const envPath = resolve(__dirname, '../.env');
console.error('Looking for .env file at:', envPath);
console.error('.env file exists:', existsSync(envPath));
// Load environment variables (non-fatal if missing — env vars can be passed directly)
// Load environment variables (non-fatal if missing - env vars can be passed directly)
if (existsSync(envPath)) {
const result = config({ path: envPath });
if (result.error) {
console.error('Warning: Error loading .env file:', result.error);
}
} else {
console.error('No .env file found — using environment variables directly');
console.error('No .env file found - using environment variables directly');
}
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

File diff suppressed because one or more lines are too long

View File

@@ -162,7 +162,7 @@ export class OgmiosProvider implements Provider {
}
}
} catch (err) {
// Koios unreachable — caller can fall back to scanning UTxOs
// Koios unreachable - caller can fall back to scanning UTxOs
}
}
@@ -310,7 +310,7 @@ export class OgmiosProvider implements Provider {
/**
* Evaluate a transaction without submitting (dry run).
* Backward-compatible alias — returns raw Ogmios response.
* Backward-compatible alias - returns raw Ogmios response.
*/
async evaluateTransaction(txCborHex: string): Promise<any> {
return this.rpc('evaluateTransaction', {

View File

@@ -3,8 +3,8 @@ import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
import type { SpendLimits, SpendStatus, AuditEntry } from './types.js';
const VECTOR_SPEND_LIMIT_PER_TX = parseInt(process.env.VECTOR_SPEND_LIMIT_PER_TX || '100000000'); // 100 ADA
const VECTOR_SPEND_LIMIT_DAILY = parseInt(process.env.VECTOR_SPEND_LIMIT_DAILY || '500000000'); // 500 ADA
const VECTOR_SPEND_LIMIT_PER_TX = parseInt(process.env.VECTOR_SPEND_LIMIT_PER_TX || '100000000'); // 100 AP3X
const VECTOR_SPEND_LIMIT_DAILY = parseInt(process.env.VECTOR_SPEND_LIMIT_DAILY || '500000000'); // 500 AP3X
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
@@ -91,7 +91,7 @@ export class SafetyLayer {
if (amountLovelace > this.limits.perTransaction) {
return {
allowed: false,
reason: `Transaction amount ${(amountLovelace / 1_000_000).toFixed(6)} ADA exceeds per-transaction limit of ${(this.limits.perTransaction / 1_000_000).toFixed(6)} ADA`,
reason: `Transaction amount ${(amountLovelace / 1_000_000).toFixed(6)} AP3X exceeds per-transaction limit of ${(this.limits.perTransaction / 1_000_000).toFixed(6)} AP3X`,
};
}
@@ -99,7 +99,7 @@ export class SafetyLayer {
const remaining = this.limits.daily - this.dailySpent;
return {
allowed: false,
reason: `Transaction would exceed daily spend limit. Daily limit: ${(this.limits.daily / 1_000_000).toFixed(6)} ADA, already spent: ${(this.dailySpent / 1_000_000).toFixed(6)} ADA, remaining: ${(remaining / 1_000_000).toFixed(6)} ADA`,
reason: `Transaction would exceed daily spend limit. Daily limit: ${(this.limits.daily / 1_000_000).toFixed(6)} AP3X, already spent: ${(this.dailySpent / 1_000_000).toFixed(6)} AP3X, remaining: ${(remaining / 1_000_000).toFixed(6)} AP3X`,
};
}

View File

@@ -5,7 +5,7 @@
import { z } from "zod";
import { Lucid, fromText, toText, Data, Constr, credentialToAddress, getAddressDetails, SLOT_CONFIG_NETWORK } from '@lucid-evolution/lucid';
// Vector slot config — resolved from chain via Ogmios queryNetwork/startTime
// Vector slot config - resolved from chain via Ogmios queryNetwork/startTime
// Cached after first query so SLOT_CONFIG_NETWORK is set before Lucid needs it
let vectorZeroTime: number | null = null;
@@ -25,13 +25,13 @@ import { rateLimiter } from './rate-limiter.js';
// Env config
const VECTOR_OGMIOS_URL = process.env.VECTOR_OGMIOS_URL || 'https://ogmios.vector.testnet.apexfusion.org';
const VECTOR_SUBMIT_URL = process.env.VECTOR_SUBMIT_URL || 'https://submit.vector.testnet.apexfusion.org/api/submit/tx';
const VECTOR_KOIOS_URL = process.env.VECTOR_KOIOS_URL || 'https://koios.vector.testnet.apexfusion.org/';
const VECTOR_KOIOS_URL = process.env.VECTOR_KOIOS_URL || 'https://v2.koios.vector.testnet.apexfusion.org/';
const VECTOR_EXPLORER_URL = process.env.VECTOR_EXPLORER_URL || 'https://vector.testnet.apexscan.org';
// Agent Registry policy ID (shared across all modules)
const AGENT_REGISTRY_POLICY = process.env.AGENT_REGISTRY_POLICY || 'be1a0a2912da180757ed3cd61b56bb8eab0188c19dc3c0e3912d2c01';
// Governance contract hashes (from deploy_state.json)
// Module contract hashes (from deploy_state.json)
// These should be set via env vars in production
const GOV_PROPOSAL_SPEND_HASH = process.env.GOV_PROPOSAL_SPEND_HASH || 'f815f51a76002d6a973e83fecf60f45473e040acee85c631fcce134d';
const GOV_PROPOSAL_MINT_HASH = process.env.GOV_PROPOSAL_MINT_HASH || 'e8f38052352a3d20c5fe025e2a02d615826a154b26f2239286b8d565';
@@ -40,11 +40,11 @@ const GOV_CRITIQUE_MINT_HASH = process.env.GOV_CRITIQUE_MINT_HASH || '2e252a8989
const GOV_ENDORSEMENT_SPEND_HASH = process.env.GOV_ENDORSEMENT_SPEND_HASH || '5fc449848d85f30287e5bc0bd2b3e95d872ef97be27f1480c12f1a9d';
const GOV_TREASURY_ADDRESS = process.env.GOV_TREASURY_ADDRESS || 'addr1wx434t2jc3m5uhdf7tq05xjdqu3q5z7a2lhrmn5mapsd43srh7ll8';
// Reference script UTxOs (CIP-33) — for validated submit
// Reference script UTxOs (CIP-33) - for validated submit
const GOV_PROPOSAL_SPEND_REF = process.env.GOV_PROPOSAL_SPEND_REF || 'c70a410c9c0c543a0a1103049680b89cbf6fd2277e8469c4d52632dc52b80996#0';
const GOV_PROPOSAL_MINT_REF = process.env.GOV_PROPOSAL_MINT_REF || 'c40b64fff5c4056689354076aa3d06431d786a4f8f0c1e492e70261d2309e50a#0';
// Infrastructure UTxOs (governance reference inputs)
// Infrastructure UTxOs (module reference inputs)
const GOV_PARAMS_UTXO = process.env.GOV_PARAMS_UTXO || '2c082e833649175b4a543a5a0cf61f9b736acdfa0d315d1184645185e9a52796#0';
const GOV_ORACLE_UTXO = process.env.GOV_ORACLE_UTXO || '7a23dfdf9468dd35cee3cad03008f2538c86834d4e5140e0ffaf2ff93e7c04a7#0';
const GOV_CROSSREFS_UTXO = process.env.GOV_CROSSREFS_UTXO || '96a4acff8be0fb96b3839ee6c9c1fa75809b94f4967218eaf813ac56b939c4b2#0';
@@ -276,7 +276,7 @@ export function registerSelfImprovementTools(server) {
server.tool(
"vector_self_improvement_browse",
"Browse governance proposals, critiques, and endorsements. Query on-chain UTxOs at governance script addresses and decode datums into human-readable format.",
"Browse improvement proposals, critiques, and endorsements. Query on-chain UTxOs at the module's script addresses and decode datums into human-readable format.",
{
entity: z.enum(["proposals", "critiques", "endorsements", "treasury"]).describe("What to browse"),
state: z.string().optional().describe("Filter proposals by state: Open, Amended, Adopted, Rejected, Expired, Withdrawn"),
@@ -388,7 +388,7 @@ Each batch UTxO holds ~30 AP3X for adoption rewards.`,
return {
content: [{
type: "text",
text: `# Governance Proposals (${items.length} found)\n\n${lines.join('\n\n') || 'No proposals match the filters.'}`,
text: `# Improvement Proposals (${items.length} found)\n\n${lines.join('\n\n') || 'No proposals match the filters.'}`,
}],
};
} else if (entity === "critiques") {
@@ -424,10 +424,10 @@ Each batch UTxO holds ~30 AP3X for adoption rewards.`,
return {
content: [{
type: "text",
text: `Failed to browse governance data: ${err.message}
text: `Failed to browse proposal data: ${err.message}
**Troubleshooting Tips:**
1. Verify the governance contracts are deployed on testnet
1. Verify the module contracts are deployed on this network
2. Check that Ogmios is reachable at ${VECTOR_OGMIOS_URL}
3. The script addresses may not have any UTxOs yet`,
}],
@@ -440,10 +440,10 @@ Each batch UTxO holds ~30 AP3X for adoption rewards.`,
server.tool(
"vector_self_improvement_submit_proposal",
"Submit a governance proposal to the Vector Self-Improvement Module. Requires staking AP3X. Provide proposalDocument (JSON string) for automatic IPFS upload via Filebase and blake2b_256 hashing, OR provide proposalHash and storageUri manually.",
"Submit an improvement proposal to the Vector Self-Improvement Module. Requires staking AP3X. Provide proposalDocument (JSON string) for automatic IPFS upload via Filebase and blake2b_256 hashing, OR provide proposalHash and storageUri manually.",
{
mnemonic: z.string().describe("15 or 24-word BIP39 mnemonic for the wallet"),
agentDid: z.string().describe("Agent DID (hex) — the asset name from Agent Registry NFT"),
agentDid: z.string().describe("Agent DID (hex) - the asset name from Agent Registry NFT"),
proposalDocument: z.string().optional().describe("Full proposal document as JSON string. Uploaded to IPFS via Filebase; hash and CID computed automatically. If provided, proposalHash and storageUri are ignored."),
proposalHash: z.string().optional().describe("blake2b_256 hash of proposal document (64 hex chars). Required if proposalDocument is not provided."),
proposalType: z.enum(["ParameterChange", "TreasurySpend", "ProtocolUpgrade", "GameActivation", "GeneralSuggestion"]).describe("Category of the proposal"),
@@ -601,7 +601,7 @@ Each batch UTxO holds ~30 AP3X for adoption rewards.`,
throw new Error(
`Reference script UTxOs missing: found ${refScriptUtxos.length}/2. ` +
`spend_ref=${GOV_PROPOSAL_SPEND_REF}, mint_ref=${GOV_PROPOSAL_MINT_REF}. ` +
`These UTxOs may have been consumed — redeploy with scripts/redeploy_ref_scripts.py ` +
`These UTxOs may have been consumed - redeploy with scripts/redeploy_ref_scripts.py ` +
`and update GOV_PROPOSAL_SPEND_REF / GOV_PROPOSAL_MINT_REF env vars.`
);
}
@@ -614,7 +614,7 @@ Each batch UTxO holds ~30 AP3X for adoption rewards.`,
);
}
// Get governance infrastructure reference inputs
// Get module infrastructure reference inputs
const govRefUtxos = await lucid.utxosByOutRef([
parseUtxoRef(GOV_PARAMS_UTXO),
parseUtxoRef(GOV_ORACLE_UTXO),
@@ -708,7 +708,7 @@ activity tracking token (\`pact_\`) minted. Visible on the Foundation dashboard.
server.tool(
"vector_self_improvement_critique",
"Submit a critique on a governance proposal. Critiques can support, oppose, or propose amendments. Requires staking AP3X. Provide critiqueDocument (JSON string) for automatic IPFS upload, or critiqueHash + storageUri manually.",
"Submit a critique on an improvement proposal. Critiques can support, oppose, or propose amendments. Requires staking AP3X. Provide critiqueDocument (JSON string) for automatic IPFS upload, or critiqueHash + storageUri manually.",
{
mnemonic: z.string().describe("15 or 24-word BIP39 mnemonic for the wallet"),
agentDid: z.string().describe("Agent DID (hex)"),
@@ -830,7 +830,7 @@ ${ipfsCid ? `**IPFS CID:** ${ipfsCid}\n**Hash (auto-computed):** ${finalHash}` :
server.tool(
"vector_self_improvement_endorse",
"Endorse a governance proposal by staking AP3X. Endorsements signal support to the Foundation Council and are weighted by stake amount.",
"Endorse an improvement proposal by staking AP3X. Endorsements signal support to the Foundation Council and are weighted by stake amount.",
{
mnemonic: z.string().describe("15 or 24-word BIP39 mnemonic for the wallet"),
agentDid: z.string().describe("Agent DID (hex)"),
@@ -861,7 +861,7 @@ ${ipfsCid ? `**IPFS CID:** ${ipfsCid}\n**Hash (auto-computed):** ${finalHash}` :
const tip = await provider.getNetworkTip?.() || { slot: 0 };
const currentSlot = tip.slot || 0;
// Build GovernanceEndorsementDatum
// Build the endorsement datum
const endorsementDatum = Data.to(new Constr(0, [
agentDid, // endorser_did
new Constr(0, [vkeyHash]), // endorser_credential
@@ -916,7 +916,7 @@ ${ipfsCid ? `**IPFS CID:** ${ipfsCid}\n**Hash (auto-computed):** ${finalHash}` :
server.tool(
"vector_self_improvement_analyze_metrics",
"Analyze governance metrics: proposal activity, adoption rate, treasury health, and engagement statistics. Read-only — no mnemonic needed.",
"Analyze proposal metrics: proposal activity, adoption rate, treasury health, and engagement statistics. Read-only - no mnemonic needed.",
{
focus: z.enum(["overview", "adoption", "treasury", "activity"]).default("overview").describe("Analysis focus area"),
},
@@ -985,7 +985,7 @@ ${Number(treasuryTotal) < 2_500_000_000 ? '**WARNING:** Treasury below 2,500 AP3
return {
content: [{
type: "text",
text: `# Governance Metrics${focus !== 'overview' ? ` (${focus})` : ''}
text: `# Proposal Metrics${focus !== 'overview' ? ` (${focus})` : ''}
## Proposals
- **Total on-chain:** ${totalCount}
@@ -1009,11 +1009,11 @@ ${Number(treasuryTotal) < 2_500_000_000 ? '\n**WARNING:** Treasury below alert t
return {
content: [{
type: "text",
text: `Failed to analyze governance metrics: ${err.message}
text: `Failed to analyze proposal metrics: ${err.message}
**Troubleshooting Tips:**
1. Verify Ogmios endpoint is reachable
2. The governance contracts may not be deployed yet`,
2. The module contracts may not be deployed yet`,
}],
};
}

View File

@@ -39,10 +39,10 @@ if (existsSync(envPath)) {
// Configuration from environment variables
const VECTOR_OGMIOS_URL = process.env.VECTOR_OGMIOS_URL || 'https://ogmios.vector.testnet.apexfusion.org';
const VECTOR_SUBMIT_URL = process.env.VECTOR_SUBMIT_URL || 'https://submit.vector.testnet.apexfusion.org/api/submit/tx';
const VECTOR_KOIOS_URL = process.env.VECTOR_KOIOS_URL || 'https://koios.vector.testnet.apexfusion.org/';
const VECTOR_KOIOS_URL = process.env.VECTOR_KOIOS_URL || 'https://v2.koios.vector.testnet.apexfusion.org/';
const VECTOR_EXPLORER_URL = process.env.VECTOR_EXPLORER_URL || 'https://vector.testnet.apexscan.org';
// Helper function to format ADA amounts
// Helper function to format AP3X amounts
function lovelaceToAda(lovelace: string | number | bigint): string {
if (lovelace === undefined || lovelace === null) return '0.000000';
try {
@@ -159,7 +159,7 @@ export async function getWalletInfo(mnemonic: string, accountIndex: number = 0):
};
}
// Send ADA transaction
// Send AP3X transaction
export async function sendAda(
recipientAddress: string,
amountAda: number,
@@ -234,8 +234,8 @@ export async function sendTokens(
throw new Error('Amount must be a positive number');
}
// Safety check on ADA portion
const adaLovelace = adaAmount ? Math.floor(adaAmount * 1_000_000) : 2_000_000; // min ~2 ADA
// Safety check on AP3X portion
const adaLovelace = adaAmount ? Math.floor(adaAmount * 1_000_000) : 2_000_000; // min ~2 AP3X
const safetyCheck = safetyLayer.checkTransaction(adaLovelace);
if (!safetyCheck.allowed) {
throw new Error(`Safety limit exceeded: ${safetyCheck.reason}`);
@@ -260,7 +260,7 @@ export async function sendTokens(
const outputLovelace = adaAmount
? BigInt(Math.floor(adaAmount * 1_000_000))
: BigInt(2_000_000); // Default min ADA
: BigInt(2_000_000); // Default min AP3X
let tx = lucid.newTx()
.pay.ToAddress(recipientAddress, {
@@ -303,7 +303,7 @@ export async function buildTransaction(
throw new Error('At least one output is required');
}
// Calculate total ADA across all outputs for safety check
// Calculate total AP3X across all outputs for safety check
const totalLovelace = outputs.reduce((sum, o) => sum + o.lovelace, 0);
const safetyCheck = safetyLayer.checkTransaction(totalLovelace);
if (!safetyCheck.allowed) {
@@ -494,7 +494,7 @@ export async function interactWithContract(
const signedTx = await completedTx.sign.withWallet().complete();
const txHash = await signedTx.submit();
// No spend recording for collecting — funds are coming back to wallet
// No spend recording for collecting - funds are coming back to wallet
return {
txHash,
@@ -508,10 +508,10 @@ export async function interactWithContract(
// Register all Vector MCP tools
export function registerVectorTools(server: McpServer) {
// vector_get_balance — Get balance for any address
// vector_get_balance - Get balance for any address
server.tool(
"vector_get_balance",
"Get ADA and token balances for a Vector address",
"Get AP3X and token balances for a Vector address",
{
address: z.string().describe("Vector address to check (addr1...)"),
},
@@ -563,7 +563,7 @@ export function registerVectorTools(server: McpServer) {
type: "text",
text: `Vector Address Balance for ${address}:
ADA Balance: ${lovelaceToAda(adaBalance)} ADA
AP3X Balance: ${lovelaceToAda(adaBalance)} AP3X
UTxO Count: ${utxos.length}
${tokens.length > 0 ? `Token Holdings (${tokens.length}):\n${tokenList}` : 'No token holdings found'}`,
@@ -581,7 +581,7 @@ ${tokens.length > 0 ? `Token Holdings (${tokens.length}):\n${tokenList}` : 'No t
}
);
// vector_get_address — Get the agent's wallet address and balance
// vector_get_address - Get the agent's wallet address and balance
server.tool(
"vector_get_address",
"Get the Vector wallet address, balance, and token holdings derived from a mnemonic",
@@ -606,7 +606,7 @@ ${tokens.length > 0 ? `Token Holdings (${tokens.length}):\n${tokenList}` : 'No t
text: `# Vector Wallet Information
Address: ${walletInfo.address}
ADA Balance: ${walletInfo.ada} ADA
AP3X Balance: ${walletInfo.ada} AP3X
UTXO Count: ${walletInfo.utxoCount}
${walletInfo.tokens.length > 0 ? `## Token Holdings (${walletInfo.tokens.length}):\n${tokenList}` : 'No token holdings found'}`,
@@ -629,7 +629,7 @@ ${walletInfo.tokens.length > 0 ? `## Token Holdings (${walletInfo.tokens.length}
}
);
// vector_get_utxos — List UTxOs for an address or the wallet
// vector_get_utxos - List UTxOs for an address or the wallet
server.tool(
"vector_get_utxos",
"List unspent transaction outputs (UTxOs) for a Vector address or a wallet derived from a mnemonic",
@@ -673,7 +673,7 @@ ${walletInfo.tokens.length > 0 ? `## Token Holdings (${walletInfo.tokens.length}
const utxoList = utxos.map((utxo, i) => {
const ada = utxo.assets['lovelace'] ? lovelaceToAda(utxo.assets['lovelace']) : '0';
const tokenCount = Object.keys(utxo.assets).filter(k => k !== 'lovelace').length;
return `${i + 1}. ${utxo.txHash}#${utxo.outputIndex} — ${ada} ADA${tokenCount > 0 ? ` + ${tokenCount} token(s)` : ''}`;
return `${i + 1}. ${utxo.txHash}#${utxo.outputIndex} - ${ada} AP3X${tokenCount > 0 ? ` + ${tokenCount} token(s)` : ''}`;
}).join('\n');
return {
@@ -698,13 +698,13 @@ ${utxoList}`,
}
);
// vector_send_apex — Send APEX with safety limits (or craft unsigned TX)
// vector_send_apex - Send APEX with safety limits (or craft unsigned TX)
server.tool(
"vector_send_apex",
"Send ADA from a wallet to a recipient address. Set unsigned_only=true to return unsigned CBOR without submitting (transaction-crafter mode).",
"Send AP3X from a wallet to a recipient address. Set unsigned_only=true to return unsigned CBOR without submitting (transaction-crafter mode).",
{
recipientAddress: z.string().describe("Recipient Vector address (addr1...)"),
amount: z.number().min(1).describe("Amount of ADA to send"),
amount: z.number().min(1).describe("Amount of AP3X to send"),
mnemonic: z.string().describe("15 or 24-word BIP39 mnemonic for the sending wallet"),
metadata: z.string().optional().describe("Optional transaction metadata in JSON format"),
unsigned_only: z.boolean().optional().default(false).describe("If true, return unsigned TX CBOR without signing or submitting"),
@@ -732,9 +732,9 @@ ${utxoList}`,
type: "text",
text: `# Unsigned Transaction (Transaction-Crafter Mode)
**Amount:** ${amount} ADA (${lovelaceAmount} lovelace)
**Amount:** ${amount} AP3X (${lovelaceAmount} lovelace)
**To:** ${recipientAddress}
**Estimated Fee:** ${lovelaceToAda(fee)} ADA
**Estimated Fee:** ${lovelaceToAda(fee)} AP3X
**Unsigned TX CBOR:**
\`\`\`
@@ -750,12 +750,12 @@ This transaction has NOT been submitted. Sign and submit it separately.`,
return {
content: [{
type: "text",
text: `# ADA Transaction Successful
text: `# AP3X Transaction Successful
Transaction Hash: ${result.txHash}
From: ${result.senderAddress}
To: ${result.recipientAddress}
Amount: ${result.amount} ADA
Amount: ${result.amount} AP3X
[View on Explorer](${result.links.explorer})`,
}],
@@ -765,7 +765,7 @@ Amount: ${result.amount} ADA
return {
content: [{
type: "text",
text: `Failed to send ADA: ${error.message}
text: `Failed to send AP3X: ${error.message}
**Troubleshooting Tips:**
1. Check that your wallet has sufficient balance
@@ -778,7 +778,7 @@ Amount: ${result.amount} ADA
}
);
// vector_send_tokens — Send native tokens with safety limits (or craft unsigned TX)
// vector_send_tokens - Send native tokens with safety limits (or craft unsigned TX)
server.tool(
"vector_send_tokens",
"Send Vector native tokens from a wallet to a recipient address. Set unsigned_only=true to return unsigned CBOR without submitting.",
@@ -788,7 +788,7 @@ Amount: ${result.amount} ADA
assetName: z.string().describe("Asset name (can be empty for policy-only tokens)"),
amount: z.string().describe("Amount of tokens to send"),
mnemonic: z.string().describe("15 or 24-word BIP39 mnemonic for the sending wallet"),
adaAmount: z.number().optional().describe("Optional ADA to include (uses minimum required if not specified)"),
adaAmount: z.number().optional().describe("Optional AP3X to include (uses minimum required if not specified)"),
unsigned_only: z.boolean().optional().default(false).describe("If true, return unsigned TX CBOR without signing or submitting"),
},
async ({ recipientAddress, policyId, assetName, amount, mnemonic, adaAmount, unsigned_only }) => {
@@ -821,8 +821,8 @@ Amount: ${result.amount} ADA
**Token:** ${formatAssetName(assetNameHex) || policyId.substring(0,8) + '...'}
**Amount:** ${amount}
**To:** ${recipientAddress}
**Included ADA:** ${lovelaceToAda(outputLovelace)} ADA
**Estimated Fee:** ${lovelaceToAda(fee)} ADA
**Included AP3X:** ${lovelaceToAda(outputLovelace)} AP3X
**Estimated Fee:** ${lovelaceToAda(fee)} AP3X
**Unsigned TX CBOR:**
\`\`\`
@@ -849,7 +849,7 @@ Token Details:
- Asset Name: ${result.token.name || '(none)'}
- Amount: ${result.token.amount}
Included ADA: ${result.ada} ADA
Included AP3X: ${result.ada} AP3X
[View on Explorer](${result.links.explorer})`,
}],
@@ -862,7 +862,7 @@ Included ADA: ${result.ada} ADA
text: `Failed to send tokens: ${error.message}
**Troubleshooting Tips:**
1. Check that your wallet has sufficient ADA and token balance
1. Check that your wallet has sufficient AP3X and token balance
2. Verify the policy ID and asset name are correct
3. Verify the recipient address is correct (addr1...)
4. Check spend limits with vector_get_spend_limits`,
@@ -872,7 +872,7 @@ Included ADA: ${result.ada} ADA
}
);
// vector_get_spend_limits — Check safety layer status
// vector_get_spend_limits - Check safety layer status
server.tool(
"vector_get_spend_limits",
"Check current spend limits and remaining daily budget",
@@ -887,7 +887,7 @@ Included ADA: ${result.ada} ADA
const log = safetyLayer.getAuditLog();
const recentTxs = log.slice(-5).reverse().map((entry) =>
`- ${entry.timestamp}: ${lovelaceToAda(entry.amountLovelace)} ADA → ${entry.recipient.substring(0, 20)}... (${entry.txHash.substring(0, 16)}...)`
`- ${entry.timestamp}: ${lovelaceToAda(entry.amountLovelace)} AP3X → ${entry.recipient.substring(0, 20)}... (${entry.txHash.substring(0, 16)}...)`
).join('\n');
return {
@@ -895,10 +895,10 @@ Included ADA: ${result.ada} ADA
type: "text",
text: `# Vector Spend Limits
Per-Transaction Limit: ${lovelaceToAda(status.perTransactionLimit)} ADA
Daily Limit: ${lovelaceToAda(status.dailyLimit)} ADA
Daily Spent: ${lovelaceToAda(status.dailySpent)} ADA
Daily Remaining: ${lovelaceToAda(status.dailyRemaining)} ADA
Per-Transaction Limit: ${lovelaceToAda(status.perTransactionLimit)} AP3X
Daily Limit: ${lovelaceToAda(status.dailyLimit)} AP3X
Daily Spent: ${lovelaceToAda(status.dailySpent)} AP3X
Daily Remaining: ${lovelaceToAda(status.dailyRemaining)} AP3X
Resets At: ${status.resetTime}
${log.length > 0 ? `## Recent Transactions (last ${Math.min(5, log.length)}):\n${recentTxs}` : 'No transactions recorded yet.'}`,
@@ -916,14 +916,14 @@ ${log.length > 0 ? `## Recent Transactions (last ${Math.min(5, log.length)}):\n$
}
);
// vector_build_transaction — Build a complex multi-output transaction
// vector_build_transaction - Build a complex multi-output transaction
server.tool(
"vector_build_transaction",
"Build a complex multi-output transaction with metadata. Set submit=true to sign and submit, or false to return unsigned CBOR for review.",
{
outputs: z.array(z.object({
address: z.string().describe("Recipient Vector address"),
lovelace: z.number().describe("Amount in lovelace (1 ADA = 1,000,000 lovelace)"),
lovelace: z.number().describe("Amount in lovelace (1 AP3X = 1,000,000 lovelace)"),
assets: z.record(z.string()).optional().describe("Optional native assets: { 'policyId+assetNameHex': 'quantity' }"),
})).min(1).describe("Transaction outputs"),
mnemonic: z.string().describe("15 or 24-word BIP39 mnemonic for the signing wallet"),
@@ -945,9 +945,9 @@ ${log.length > 0 ? `## Recent Transactions (last ${Math.min(5, log.length)}):\n$
text: `# Transaction Submitted
Transaction Hash: ${result.txHash}
Fee: ${result.feeAda} ADA
Fee: ${result.feeAda} AP3X
Outputs: ${result.outputCount}
Total ADA Sent: ${result.totalAda} ADA
Total AP3X Sent: ${result.totalAda} AP3X
[View on Explorer](${result.links?.explorer})`,
}],
@@ -960,9 +960,9 @@ Total ADA Sent: ${result.totalAda} ADA
text: `# Transaction Built (Not Submitted)
Transaction Hash: ${result.txHash}
Fee: ${result.feeAda} ADA
Fee: ${result.feeAda} AP3X
Outputs: ${result.outputCount}
Total ADA: ${result.totalAda} ADA
Total AP3X: ${result.totalAda} AP3X
CBOR (hex): ${result.txCbor.substring(0, 200)}${result.txCbor.length > 200 ? '...' : ''}
@@ -978,7 +978,7 @@ Use vector_dry_run with this CBOR to simulate, or call vector_build_transaction
**Troubleshooting Tips:**
1. Verify all recipient addresses are valid (addr1...)
2. Ensure wallet has enough ADA for outputs + fees
2. Ensure wallet has enough AP3X for outputs + fees
3. Check spend limits with vector_get_spend_limits`,
}],
};
@@ -986,10 +986,10 @@ Use vector_dry_run with this CBOR to simulate, or call vector_build_transaction
}
);
// vector_dry_run — Simulate a transaction without submitting
// vector_dry_run - Simulate a transaction without submitting
server.tool(
"vector_dry_run",
"Simulate a transaction without submitting — returns fee estimate and validation result",
"Simulate a transaction without submitting - returns fee estimate and validation result",
{
txCbor: z.string().optional().describe("Hex-encoded CBOR of a built transaction to evaluate"),
outputs: z.array(z.object({
@@ -1071,7 +1071,7 @@ Use vector_dry_run with this CBOR to simulate, or call vector_build_transaction
executionUnits: (totalMemory > 0 || totalCpu > 0) ? { memory: totalMemory, cpu: totalCpu } : undefined,
};
} catch (evalErr) {
// evaluateTransaction failed — still return fee if we built the tx
// evaluateTransaction failed - still return fee if we built the tx
if (feeFromBuild) {
evalResult = {
valid: true,
@@ -1095,7 +1095,7 @@ Use vector_dry_run with this CBOR to simulate, or call vector_build_transaction
text: `# Dry Run Result
Valid: ${evalResult.valid ? 'Yes' : 'No'}
Estimated Fee: ${evalResult.feeAda} ADA (${evalResult.fee} lovelace)
Estimated Fee: ${evalResult.feeAda} AP3X (${evalResult.fee} lovelace)
${evalResult.executionUnits ? `Execution Units: Memory ${evalResult.executionUnits.memory}, CPU ${evalResult.executionUnits.cpu}` : ''}
${evalResult.error ? `\nNote: ${evalResult.error}` : ''}
@@ -1114,7 +1114,7 @@ No transaction was submitted to the network.`,
}
);
// vector_get_transaction_history — Get transaction history via Koios
// vector_get_transaction_history - Get transaction history via Koios
server.tool(
"vector_get_transaction_history",
"Get transaction history for a Vector address via Koios indexed queries",
@@ -1156,7 +1156,7 @@ No transaction was submitted to the network.`,
const txList = txs.map((tx, i) => {
const feeAda = tx.fee ? lovelaceToAda(tx.fee) : 'N/A';
return `${i + 1}. ${tx.txHash}\n Block: ${tx.blockHeight} | Time: ${tx.blockTime} | Fee: ${feeAda} ADA`;
return `${i + 1}. ${tx.txHash}\n Block: ${tx.blockHeight} | Time: ${tx.blockTime} | Fee: ${feeAda} AP3X`;
}).join('\n\n');
return {
@@ -1188,7 +1188,7 @@ ${txList}
}
);
// vector_deploy_contract — Deploy a Plutus/Aiken smart contract
// vector_deploy_contract - Deploy a Plutus/Aiken smart contract
server.tool(
"vector_deploy_contract",
"Deploy a Plutus/Aiken smart contract to Vector by sending funds to its script address",
@@ -1197,7 +1197,7 @@ ${txList}
scriptType: z.enum(["PlutusV1", "PlutusV2", "PlutusV3"]).describe("Script version"),
mnemonic: z.string().describe("15 or 24-word BIP39 mnemonic for the deploying wallet"),
initialDatum: z.string().optional().describe("Initial datum as CBOR hex. Use 'd87980' for void/unit datum. Defaults to void if omitted."),
lovelaceAmount: z.number().optional().describe("ADA to lock at the script address in lovelace (default: 2,000,000 = 2 ADA)"),
lovelaceAmount: z.number().optional().describe("AP3X to lock at the script address in lovelace (default: 2,000,000 = 2 AP3X)"),
},
async ({ scriptCbor, scriptType, mnemonic, initialDatum, lovelaceAmount }) => {
const rateCheck = rateLimiter.check();
@@ -1237,7 +1237,7 @@ Funds locked at the script address. Use vector_interact_contract to interact wit
**Troubleshooting Tips:**
1. Verify the script CBOR is valid hex (compiled Aiken or Plutus output)
2. Ensure wallet has sufficient ADA for the locked amount + fees
2. Ensure wallet has sufficient AP3X for the locked amount + fees
3. Check that the script type matches the compiled version (PlutusV1/V2/V3)
4. Check spend limits with vector_get_spend_limits`,
}],
@@ -1246,10 +1246,10 @@ Funds locked at the script address. Use vector_interact_contract to interact wit
}
);
// vector_interact_contract — Interact with a deployed smart contract
// vector_interact_contract - Interact with a deployed smart contract
server.tool(
"vector_interact_contract",
"Interact with a deployed Plutus/Aiken smart contract — lock funds or spend from it",
"Interact with a deployed Plutus/Aiken smart contract - lock AP3X or spend from it",
{
scriptCbor: z.string().describe("Compiled Plutus/Aiken script in CBOR hex"),
scriptType: z.enum(["PlutusV1", "PlutusV2", "PlutusV3"]).describe("Script version"),
@@ -1257,7 +1257,7 @@ Funds locked at the script address. Use vector_interact_contract to interact wit
mnemonic: z.string().describe("15 or 24-word BIP39 mnemonic for the wallet"),
redeemer: z.string().optional().describe("Redeemer as CBOR hex (required for spend, use 'd87980' for void)"),
datum: z.string().optional().describe("Datum as CBOR hex (required for lock, use 'd87980' for void)"),
lovelaceAmount: z.number().optional().describe("Lovelace to lock (for lock action, default: 2,000,000 = 2 ADA)"),
lovelaceAmount: z.number().optional().describe("Lovelace to lock (for lock action, default: 2,000,000 = 2 AP3X)"),
utxoRef: z.object({
txHash: z.string(),
outputIndex: z.number(),
@@ -1307,8 +1307,8 @@ Funds ${actionVerb} the script address.
**Troubleshooting Tips:**
1. For 'spend': ensure the script address has UTxOs and the redeemer satisfies the validator
2. For 'lock': ensure wallet has sufficient ADA and the datum matches the script's expectations
3. Spending requires collateral — ensure wallet has a pure-ADA UTxO (no native tokens)
2. For 'lock': ensure wallet has sufficient AP3X and the datum matches the script's expectations
3. Spending requires collateral - ensure wallet has a pure-AP3X UTxO (no native tokens)
4. Verify the script CBOR matches the deployed script exactly
5. Check spend limits with vector_get_spend_limits`,
}],