Core
The A3Stack class: one object, three capabilities. Identity, payments, and MCP combined.
What is @a3stack/core?
@a3stack/core is the all-in-one package that combines identity, payments, and data into a single A3Stack class. It also re-exports everything from the other packages, so you can do one install and one import.
Use A3Stack when you want the simplest possible setup. Use the individual packages (@a3stack/identity, etc.) when you need more control.
Initialization
import { A3Stack } from "@a3stack/core";
import { base } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { z } from "zod";
const agent = new A3Stack({
// Identity config
account: privateKeyToAccount(process.env.PRIVATE_KEY),
chain: base,
rpc: "https://mainnet.base.org", // optional
// Server config (optional — omit if not serving tools)
server: {
name: "MyAgent",
version: "1.0.0",
port: 3000,
payment: {
amount: "10000", // 0.01 USDC per call
// payTo defaults to this wallet
description: "MyAgent: 0.01 USDC per call",
},
},
});Configuration
interface A3StackConfig {
account: Account; // viem Account (signer)
chain: Chain; // viem Chain (e.g. base)
rpc?: string; // optional RPC URL override
server?: {
name: string;
version?: string; // default: "1.0.0"
port?: number; // default: 3000
payment?: {
amount: string; // USDC base units
payTo?: string; // defaults to account.address
asset?: string; // defaults to USDC_BASE
network?: string; // defaults to "eip155:8453"
description?: string;
freeTools?: string[];
};
};
}Methods
agent.tool()
Register a tool with the MCP server. Requires server config to be set.
// Register a tool (same API as MCP SDK)
agent.tool(
"my-tool", // tool name
"Does a thing", // description
{ input: z.string() }, // input schema (zod)
async ({ input }) => ({
content: [{ type: "text", text: `Result: ${input}` }],
})
);agent.start() / agent.stop()
Start or stop the MCP server.
// Start the MCP server
const { url } = await agent.start();
console.log(`Serving at ${url}`);
// → http://localhost:3000/mcp
// Stop when done
await agent.stop();agent.register()
Register your agent on-chain via ERC-8004. One-time, costs a small amount of gas.
// Register on-chain (one-time, costs gas)
const { agentId, globalId, txHash } = await agent.register({
name: "MyAgent",
description: "My paid AI agent service",
x402Support: true,
active: true,
includeServerEndpoint: true, // auto-adds MCP URL to services
mcpUrl: "https://mcp.myagent.ai/mcp", // optional override
});
console.log(`Global ID: ${globalId}`);
// → "eip155:8453:0x8004...#42"agent.connect()
Connect to another agent's MCP server by global ID. Returns an MCP client with auto-payment.
// Connect to another agent (auto-pays x402 if needed)
const client = await agent.connect("eip155:8453:0x8004...#9999");
const tools = await client.listTools();
const result = await client.callTool("some-tool", { query: "hello" });
const identity = await client.getAgentIdentity();
await client.close();agent.verify()
// Verify another agent's on-chain identity
const verification = await agent.verify("eip155:8453:0x8004...#9999");
console.log(verification.valid); // true / false
console.log(verification.owner); // "0x..."
console.log(verification.registration?.name); // "SomeAgent"agent.getBalance()
// Check this agent's USDC balance
const balance = await agent.getBalance();
// { amount: 5000000n, formatted: "5.000000", symbol: "USDC" }agent.getMcpEndpoint()
// Resolve another agent's MCP endpoint
const url = await agent.getMcpEndpoint("eip155:8453:0x8004...#9999");
// "https://mcp.someagent.ai/mcp"Standalone utilities
These are re-exported from the sub-packages and work without instantiating A3Stack:
import { probeAgent } from "@a3stack/core";
// Probe without instantiating A3Stack (no wallet needed)
const info = await probeAgent("eip155:8453:0x8004...#2376");import { findAllRegistrations } from "@a3stack/core";
// Find all ERC-8004 registrations for a wallet across all 17 chains
const regs = await findAllRegistrations("0x1be93C...");Full example
import { A3Stack } from "@a3stack/core";
import { base } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { z } from "zod";
import { USDC_BASE } from "@a3stack/payments";
async function main() {
const account = privateKeyToAccount(process.env.PRIVATE_KEY);
// Initialize
const agent = new A3Stack({
account,
chain: base,
server: {
name: "DemoAgent",
payment: { amount: "1000", asset: USDC_BASE },
},
});
// Register tools
agent.tool("hello", { name: z.string().optional() }, async ({ name }) => ({
content: [{ type: "text", text: `Hello, ${name ?? "world"}!` }],
}));
// Start serving
const { url } = await agent.start();
console.log(`Agent running at ${url}`);
// Check balance
const balance = await agent.getBalance();
console.log(`USDC: ${balance.formatted}`);
// Verify another agent
const check = await agent.verify("eip155:8453:0x8004...#9999");
if (check.valid) {
const client = await agent.connect("eip155:8453:0x8004...#9999");
const result = await client.callTool("some-tool", {});
console.log(result);
await client.close();
}
}
main().catch(console.error);Package re-exports
@a3stack/core re-exports everything from the sub-packages. You can use it as a single import for everything:
| Export | From |
|---|---|
A3Stack | @a3stack/core |
probeAgent, findAllRegistrations | @a3stack/core |
AgentIdentity, verifyAgent, getMcpEndpoint, ... | @a3stack/identity |
createPaymentClient, createPaymentServer, PaymentClient, USDC_BASE, ... | @a3stack/payments |
createAgentMcpServer, createAgentMcpClient | @a3stack/data |