@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 +34 -0
- package/src/agent.ts +262 -0
- package/src/index.ts +73 -0
- package/src/types.ts +55 -0
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
|
+
}
|