@a3stack/core 0.1.0

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/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@a3stack/core",
3
+ "version": "0.1.0",
4
+ "description": "A3Stack SDK — identity + payments + data for AI agents",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "scripts": {
17
+ "build": "tsup src/index.ts --format esm,cjs --dts --outDir dist",
18
+ "typecheck": "tsc --noEmit"
19
+ },
20
+ "dependencies": {
21
+ "@a3stack/identity": "file:../identity",
22
+ "@a3stack/payments": "file:../payments",
23
+ "@a3stack/data": "file:../data",
24
+ "viem": "^2.39.3",
25
+ "zod": "^3.24.2"
26
+ },
27
+ "devDependencies": {
28
+ "tsup": "^8.0.0",
29
+ "typescript": "^5.4.0"
30
+ },
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ }
34
+ }
package/src/agent.ts ADDED
@@ -0,0 +1,262 @@
1
+ /**
2
+ * A3Stack — the all-in-one glue layer
3
+ * Combines identity + payments + data into one clean interface
4
+ */
5
+
6
+ import type { Account } from "viem";
7
+ import { z } from "zod";
8
+ import { AgentIdentity, verifyAgent, getMcpEndpoint, IDENTITY_REGISTRY_ADDRESS } from "@a3stack/identity";
9
+ import type { VerificationResult } from "@a3stack/identity";
10
+ import { PaymentClient } from "@a3stack/payments";
11
+ import { AgentMcpServerInstance, createAgentMcpClient, probeAgent } from "@a3stack/data";
12
+ import type { AgentProbeResult } from "@a3stack/data";
13
+ import type { AgentMcpClientInstance } from "@a3stack/data";
14
+ import type { A3StackConfig, A3StackRegisterOptions } from "./types.js";
15
+
16
+ export class A3Stack {
17
+ private config: A3StackConfig;
18
+ private identity: AgentIdentity;
19
+ private payer: PaymentClient;
20
+ private mcpServer?: AgentMcpServerInstance;
21
+ private _agentId?: number;
22
+ private _serverUrl?: string;
23
+
24
+ constructor(config: A3StackConfig) {
25
+ this.config = config;
26
+
27
+ // Initialize identity manager
28
+ this.identity = new AgentIdentity({
29
+ account: config.account,
30
+ chain: config.chain,
31
+ rpc: config.rpc,
32
+ });
33
+
34
+ // Initialize payment client
35
+ this.payer = new PaymentClient({
36
+ account: config.account,
37
+ chains: [`eip155:${config.chain.id}`, "eip155:*"],
38
+ ...config.payer,
39
+ });
40
+
41
+ // Initialize MCP server if configured
42
+ if (config.server) {
43
+ // Determine payTo address (default to agent's own wallet)
44
+ const payTo = config.server.payment?.payTo ?? config.account.address;
45
+
46
+ this.mcpServer = new AgentMcpServerInstance({
47
+ name: config.server.name,
48
+ version: config.server.version ?? "0.1.0",
49
+ port: config.server.port ?? 3000,
50
+ cors: config.server.cors ?? true,
51
+ payment: config.server.payment
52
+ ? {
53
+ ...config.server.payment,
54
+ payTo,
55
+ }
56
+ : undefined,
57
+ });
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Register this agent on-chain via ERC-8004.
63
+ * Call this once to create your agent identity.
64
+ */
65
+ async register(options: A3StackRegisterOptions): Promise<{
66
+ agentId: number;
67
+ txHash: `0x${string}`;
68
+ globalId: string;
69
+ }> {
70
+ // Check if already registered
71
+ const { registered } = await this.identity.isRegistered();
72
+ if (registered) {
73
+ throw new Error(
74
+ `Agent is already registered on chain ${this.config.chain.id}. ` +
75
+ `Use updateIdentity() to change your registration.`
76
+ );
77
+ }
78
+
79
+ // Auto-add MCP server endpoint if configured
80
+ const services = [...(options.services ?? [])];
81
+ if (
82
+ options.includeServerEndpoint !== false &&
83
+ this.config.server &&
84
+ this._serverUrl
85
+ ) {
86
+ const hasMcp = services.some((s) => s.name.toUpperCase() === "MCP");
87
+ if (!hasMcp) {
88
+ services.push({
89
+ name: "MCP",
90
+ endpoint: options.mcpUrl ?? this._serverUrl,
91
+ version: "2025-06-18",
92
+ });
93
+ }
94
+ }
95
+
96
+ const result = await this.identity.register({ ...options, services });
97
+ this._agentId = result.agentId;
98
+ return result;
99
+ }
100
+
101
+ /**
102
+ * Start the MCP server (if configured).
103
+ * Returns the server URL.
104
+ */
105
+ async start(port?: number): Promise<{ url: string }> {
106
+ if (!this.mcpServer) {
107
+ throw new Error(
108
+ "No server configured. Pass server config to A3Stack constructor."
109
+ );
110
+ }
111
+ const result = await this.mcpServer.listen(port);
112
+ this._serverUrl = result.url;
113
+ return result;
114
+ }
115
+
116
+ /**
117
+ * Stop the MCP server
118
+ */
119
+ async stop(): Promise<void> {
120
+ await this.mcpServer?.close();
121
+ }
122
+
123
+ /**
124
+ * Register a tool on this agent's MCP server.
125
+ * Handler must return a CallToolResult: { content: [{ type: "text", text: string }] }
126
+ */
127
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
+ tool(
129
+ name: string,
130
+ description: string,
131
+ paramsSchema: Record<string, z.ZodTypeAny>,
132
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
133
+ handler: (args: any) => Promise<any>
134
+ ): void {
135
+ if (!this.mcpServer) {
136
+ throw new Error("No server configured. Pass server config to A3Stack constructor.");
137
+ }
138
+ this.mcpServer.tool(name, description, paramsSchema, handler);
139
+ }
140
+
141
+ /**
142
+ * Register a resource on this agent's MCP server
143
+ */
144
+ resource(
145
+ name: string,
146
+ uri: string,
147
+ description: string,
148
+ handler: (uri: URL) => Promise<{ contents: Array<{ uri: string; text: string; mimeType?: string }> }>
149
+ ): void {
150
+ if (!this.mcpServer) {
151
+ throw new Error("No server configured.");
152
+ }
153
+ this.mcpServer.resource(name, uri, description, handler);
154
+ }
155
+
156
+ /**
157
+ * Connect to another agent by ERC-8004 global ID.
158
+ * Auto-resolves MCP endpoint and handles payment.
159
+ */
160
+ async connect(agentGlobalId: string): Promise<AgentMcpClientInstance> {
161
+ return createAgentMcpClient({
162
+ agentId: agentGlobalId,
163
+ payer: {
164
+ account: this.config.account,
165
+ maxAmount: this.config.payer?.maxAmountPerRequest,
166
+ },
167
+ });
168
+ }
169
+
170
+ /**
171
+ * Connect to another agent by direct URL (no identity verification)
172
+ */
173
+ async connectUrl(url: string): Promise<AgentMcpClientInstance> {
174
+ return createAgentMcpClient({
175
+ url,
176
+ payer: {
177
+ account: this.config.account,
178
+ maxAmount: this.config.payer?.maxAmountPerRequest,
179
+ },
180
+ });
181
+ }
182
+
183
+ /**
184
+ * Verify another agent's identity before interacting
185
+ */
186
+ async verify(agentGlobalId: string): Promise<VerificationResult> {
187
+ return verifyAgent(agentGlobalId);
188
+ }
189
+
190
+ /**
191
+ * Probe another agent — discover capabilities without connecting.
192
+ * Returns identity, endpoints, payment requirements, services.
193
+ * Read-only, no wallet needed for the target agent.
194
+ */
195
+ async probe(agentGlobalId: string): Promise<AgentProbeResult> {
196
+ return probeAgent(agentGlobalId);
197
+ }
198
+
199
+ /**
200
+ * Get another agent's MCP endpoint
201
+ */
202
+ async getMcpEndpoint(agentGlobalId: string): Promise<string | null> {
203
+ return getMcpEndpoint(agentGlobalId);
204
+ }
205
+
206
+ /**
207
+ * Check USDC balance on current chain
208
+ */
209
+ async getBalance() {
210
+ return this.payer.getBalance(`eip155:${this.config.chain.id}`, this.config.rpc);
211
+ }
212
+
213
+ /**
214
+ * The payment-wrapped fetch for making calls to paid APIs
215
+ */
216
+ get fetch() {
217
+ return this.payer.fetch;
218
+ }
219
+
220
+ /**
221
+ * Current agent ID (set after register())
222
+ */
223
+ get agentId(): number | undefined {
224
+ return this._agentId;
225
+ }
226
+
227
+ /**
228
+ * Current global agent ID (set after register() + start())
229
+ */
230
+ get globalId(): string | undefined {
231
+ if (!this._agentId) return undefined;
232
+ return `eip155:${this.config.chain.id}:${IDENTITY_REGISTRY_ADDRESS}#${this._agentId}`;
233
+ }
234
+
235
+ /**
236
+ * MCP server URL (set after start())
237
+ */
238
+ get serverUrl(): string | undefined {
239
+ return this._serverUrl;
240
+ }
241
+
242
+ /**
243
+ * Raw identity manager for advanced ERC-8004 operations
244
+ */
245
+ get identityManager(): AgentIdentity {
246
+ return this.identity;
247
+ }
248
+
249
+ /**
250
+ * Raw payment client for advanced payment operations
251
+ */
252
+ get paymentClient(): PaymentClient {
253
+ return this.payer;
254
+ }
255
+
256
+ /**
257
+ * Raw MCP server for advanced operations
258
+ */
259
+ get mcpServerInstance(): AgentMcpServerInstance | undefined {
260
+ return this.mcpServer;
261
+ }
262
+ }
package/src/index.ts ADDED
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @a3stack/core
3
+ * A3Stack SDK — identity + payments + data for AI agents
4
+ *
5
+ * The all-in-one glue layer. Import just what you need:
6
+ * import { A3Stack } from "@a3stack/core"
7
+ *
8
+ * Or use individual packages for more control:
9
+ * import { AgentIdentity } from "@a3stack/identity"
10
+ * import { PaymentClient } from "@a3stack/payments"
11
+ * import { createAgentMcpServer } from "@a3stack/data"
12
+ */
13
+
14
+ // Main class
15
+ export { A3Stack } from "./agent.js";
16
+
17
+ // Re-export everything from sub-packages for convenience
18
+ export {
19
+ // Identity
20
+ AgentIdentity,
21
+ verifyAgent,
22
+ parseAgentId,
23
+ formatAgentId,
24
+ fetchRegistrationFile,
25
+ getMcpEndpoint,
26
+ getA2aEndpoint,
27
+ getAgentCount,
28
+ findAllRegistrations,
29
+ IDENTITY_REGISTRY_ADDRESS,
30
+ SUPPORTED_CHAINS,
31
+ } from "@a3stack/identity";
32
+
33
+ export type {
34
+ AgentRegistrationFile,
35
+ AgentService,
36
+ AgentRef,
37
+ VerificationResult,
38
+ RegisterOptions,
39
+ RegisterResult,
40
+ } from "@a3stack/identity";
41
+
42
+ export {
43
+ // Payments
44
+ PaymentClient,
45
+ PaymentServer,
46
+ createPaymentClient,
47
+ createPaymentServer,
48
+ USDC_BASE,
49
+ USDC_ETH,
50
+ DEFAULT_NETWORK,
51
+ NETWORK_USDC,
52
+ } from "@a3stack/payments";
53
+
54
+ export type {
55
+ PaymentClientConfig,
56
+ PaymentServerConfig,
57
+ PaymentDetails,
58
+ PaymentBalance,
59
+ PaymentVerifyResult,
60
+ } from "@a3stack/payments";
61
+
62
+ export {
63
+ // Data / MCP
64
+ createAgentMcpServer,
65
+ createAgentMcpClient,
66
+ AgentMcpServerInstance,
67
+ AgentMcpClientInstance,
68
+ probeAgent,
69
+ } from "@a3stack/data";
70
+
71
+ export type { AgentMcpServerConfig, AgentMcpClientConfig, AgentProbeResult } from "@a3stack/data";
72
+
73
+ export type { A3StackConfig, A3StackRegisterOptions } from "./types.js";
package/src/types.ts ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @a3stack/core — Type Definitions
3
+ */
4
+
5
+ import type { Chain, Account } from "viem";
6
+ import type { RegisterOptions } from "@a3stack/identity";
7
+ import type { PaymentServerConfig, PaymentClientConfig } from "@a3stack/payments";
8
+
9
+ export interface A3StackConfig {
10
+ /**
11
+ * viem Account (e.g. from privateKeyToAccount())
12
+ * Must have signTransaction for on-chain write operations (register, setAgentURI)
13
+ * Can be a read-only account (address only) for read/verify operations
14
+ */
15
+ account: Account;
16
+
17
+ /**
18
+ * viem Chain (e.g. import { base } from "viem/chains")
19
+ */
20
+ chain: Chain;
21
+
22
+ /**
23
+ * RPC URL override for the chain
24
+ */
25
+ rpc?: string;
26
+
27
+ /**
28
+ * MCP Server configuration.
29
+ * If provided, this A3Stack instance can serve MCP tools.
30
+ */
31
+ server?: {
32
+ name: string;
33
+ version?: string;
34
+ port?: number;
35
+ cors?: boolean;
36
+ /** Require payment to call tools */
37
+ payment?: Omit<PaymentServerConfig, "payTo"> & { payTo?: `0x${string}` };
38
+ };
39
+
40
+ /**
41
+ * Payment client configuration for calling other agents.
42
+ * Defaults to auto-configured from account + chain.
43
+ */
44
+ payer?: Omit<PaymentClientConfig, "account">;
45
+ }
46
+
47
+ export interface A3StackRegisterOptions extends RegisterOptions {
48
+ /**
49
+ * If true, auto-include the current MCP server URL in services.
50
+ * Only valid if server.port is configured.
51
+ */
52
+ includeServerEndpoint?: boolean;
53
+ /** Override the MCP URL to include in services */
54
+ mcpUrl?: string;
55
+ }