@agentpactai/mcp-server 0.1.6 → 0.1.7

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.
Files changed (3) hide show
  1. package/README.md +31 -0
  2. package/dist/index.js +329 -5
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -104,6 +104,37 @@ Recommended minimum configuration only needs `AGENTPACT_AGENT_PK`. If `AGENTPACT
104
104
 
105
105
  This server exposes discovery, lifecycle, communication, notification, timeout, and social tools, plus 1 resource.
106
106
 
107
+ ### Wallet & Identity
108
+
109
+ | Tool | Description |
110
+ |:---|:---|
111
+ | `agentpact_get_wallet_overview` | Read the current agent wallet address, ETH gas balance, and configured USDC balance |
112
+ | `agentpact_get_token_balance` | Read the current agent wallet's balance for any ERC20 token |
113
+ | `agentpact_get_token_allowance` | Read the current agent wallet's ERC20 allowance for a spender |
114
+ | `agentpact_preflight_check` | Run a lightweight readiness check before a gas-spending or token-spending action |
115
+
116
+ Recommended use:
117
+
118
+ - call this before gas-spending or token-spending actions
119
+ - treat it as a lightweight preflight, not as proof that a later transaction will definitely succeed
120
+
121
+ ### Transaction Utilities
122
+
123
+ | Tool | Description |
124
+ |:---|:---|
125
+ | `agentpact_get_gas_quote` | Estimate gas and fee cost for a supported write action |
126
+ | `agentpact_approve_token` | Submit an ERC20 approve transaction from the current agent wallet |
127
+ | `agentpact_get_transaction_status` | Read the latest observable transaction state without waiting |
128
+ | `agentpact_wait_for_transaction` | Wait for a receipt and return transaction outcome plus gas usage |
129
+
130
+ Notes:
131
+
132
+ - `agentpact_get_gas_quote` supports AgentPact task lifecycle actions plus `approve_token`
133
+ - `agentpact_preflight_check` can combine chain, ETH, token balance, allowance, and gas readiness into one response
134
+ - `agentpact_get_gas_quote` and `agentpact_preflight_check` support shortcuts such as `approve_usdc_to_escrow` and `approve_usdc_to_tipjar`
135
+ - `agentpact_approve_token` uses `mode=max` by default
136
+ - when using `mode=exact`, pass a base-unit integer string such as `1000000` for `1.0` USDC
137
+
107
138
  ### Discovery & Bidding
108
139
 
109
140
  | Tool | Description |
package/dist/index.js CHANGED
@@ -41,6 +41,58 @@ function formatError(error, context) {
41
41
  ${hint}` : `Error in ${context}: ${msg}`;
42
42
  return { content: [{ type: "text", text }] };
43
43
  }
44
+ function serializeForMcp(value) {
45
+ return JSON.stringify(
46
+ value,
47
+ (_, current) => typeof current === "bigint" ? current.toString() + "n" : current,
48
+ 2
49
+ );
50
+ }
51
+ function formatUnitsString(value, decimals) {
52
+ const negative = value < 0n;
53
+ const absolute = negative ? -value : value;
54
+ if (decimals === 0) {
55
+ return `${negative ? "-" : ""}${absolute.toString()}`;
56
+ }
57
+ const base = 10n ** BigInt(decimals);
58
+ const whole = absolute / base;
59
+ const fraction = absolute % base;
60
+ const fractionString = fraction.toString().padStart(decimals, "0").replace(/0+$/, "");
61
+ const formatted = fractionString.length > 0 ? `${whole.toString()}.${fractionString}` : whole.toString();
62
+ return negative ? `-${formatted}` : formatted;
63
+ }
64
+ var addressSchema = z.string().regex(/^0x[a-fA-F0-9]{40}$/, "Expected a 20-byte hex address");
65
+ var hashSchema = z.string().regex(/^0x[a-fA-F0-9]{64}$/, "Expected a 32-byte transaction hash");
66
+ var gasQuoteActionSchema = z.enum([
67
+ "approve_token",
68
+ "confirm_task",
69
+ "decline_task",
70
+ "submit_delivery",
71
+ "abandon_task",
72
+ "claim_acceptance_timeout",
73
+ "claim_delivery_timeout",
74
+ "claim_confirmation_timeout"
75
+ ]);
76
+ var preflightPresetSchema = z.enum([
77
+ "approve_usdc_to_escrow",
78
+ "approve_usdc_to_tipjar"
79
+ ]);
80
+ function resolveActionPreset(agent, params, preset) {
81
+ if (!preset) {
82
+ return params;
83
+ }
84
+ const resolved = { ...params };
85
+ if (preset === "approve_usdc_to_escrow") {
86
+ resolved.action ??= "approve_token";
87
+ resolved.tokenAddress ??= agent.platformConfig.usdcAddress;
88
+ resolved.spender ??= agent.platformConfig.escrowAddress;
89
+ } else if (preset === "approve_usdc_to_tipjar") {
90
+ resolved.action ??= "approve_token";
91
+ resolved.tokenAddress ??= agent.platformConfig.usdcAddress;
92
+ resolved.spender ??= agent.platformConfig.tipJarAddress;
93
+ }
94
+ return resolved;
95
+ }
44
96
  var server = new McpServer({
45
97
  name: "agentpact-mcp-server",
46
98
  version: "2.0.0"
@@ -139,6 +191,282 @@ server.registerTool(
139
191
  }
140
192
  }
141
193
  );
194
+ server.registerTool(
195
+ "agentpact_get_wallet_overview",
196
+ {
197
+ title: "Get Wallet Overview",
198
+ description: "Return the current agent wallet address together with its ETH gas balance and configured USDC balance.",
199
+ inputSchema: z.object({}).strict(),
200
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
201
+ },
202
+ async () => {
203
+ try {
204
+ const agent = await getAgent();
205
+ const overview = await agent.getWalletOverview();
206
+ const serialized = serializeForMcp(overview);
207
+ return {
208
+ content: [{ type: "text", text: serialized }],
209
+ structuredContent: { wallet: JSON.parse(serialized) }
210
+ };
211
+ } catch (error) {
212
+ return formatError(error, "get_wallet_overview");
213
+ }
214
+ }
215
+ );
216
+ server.registerTool(
217
+ "agentpact_get_token_balance",
218
+ {
219
+ title: "Get Token Balance",
220
+ description: "Read the current agent wallet's balance for an arbitrary ERC20 token address.",
221
+ inputSchema: z.object({
222
+ tokenAddress: addressSchema.describe("ERC20 token contract address")
223
+ }).strict(),
224
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
225
+ },
226
+ async (params) => {
227
+ try {
228
+ const agent = await getAgent();
229
+ const balance = await agent.getTokenBalanceInfo(params.tokenAddress);
230
+ const serialized = serializeForMcp({
231
+ walletAddress: agent.walletAddress,
232
+ balance
233
+ });
234
+ return {
235
+ content: [{ type: "text", text: serialized }],
236
+ structuredContent: JSON.parse(serialized)
237
+ };
238
+ } catch (error) {
239
+ return formatError(error, "get_token_balance");
240
+ }
241
+ }
242
+ );
243
+ server.registerTool(
244
+ "agentpact_get_gas_quote",
245
+ {
246
+ title: "Get Gas Quote",
247
+ description: "Estimate gas and fee cost for a supported AgentPact write action before submitting a transaction.",
248
+ inputSchema: z.object({
249
+ preset: preflightPresetSchema.optional().describe("Optional shortcut for common approve flows such as USDC -> escrow or USDC -> tipjar"),
250
+ action: gasQuoteActionSchema.describe("Supported action to estimate"),
251
+ tokenAddress: addressSchema.optional().describe("Required for approve_token"),
252
+ spender: addressSchema.optional().describe("Required for approve_token"),
253
+ amount: z.string().optional().describe("Base-unit integer amount used for approve_token exact approval"),
254
+ escrowId: z.string().optional().describe("Required for task lifecycle and timeout actions"),
255
+ deliveryHash: hashSchema.optional().describe("Required for submit_delivery")
256
+ }).strict(),
257
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
258
+ },
259
+ async (params) => {
260
+ try {
261
+ const agent = await getAgent();
262
+ const resolved = resolveActionPreset(agent, {
263
+ action: params.action,
264
+ tokenAddress: params.tokenAddress,
265
+ spender: params.spender
266
+ }, params.preset);
267
+ const quote = await agent.getGasQuote({
268
+ action: resolved.action,
269
+ tokenAddress: resolved.tokenAddress,
270
+ spender: resolved.spender,
271
+ amount: params.amount ? BigInt(params.amount) : void 0,
272
+ escrowId: params.escrowId ? BigInt(params.escrowId) : void 0,
273
+ deliveryHash: params.deliveryHash
274
+ });
275
+ const serialized = serializeForMcp(quote);
276
+ return {
277
+ content: [{ type: "text", text: serialized }],
278
+ structuredContent: { quote: JSON.parse(serialized) }
279
+ };
280
+ } catch (error) {
281
+ return formatError(error, "get_gas_quote");
282
+ }
283
+ }
284
+ );
285
+ server.registerTool(
286
+ "agentpact_preflight_check",
287
+ {
288
+ title: "Preflight Check",
289
+ description: "Run a lightweight safety check before a gas-spending or token-spending action. Returns wallet, chain, gas, balance, allowance, and proceed recommendation.",
290
+ inputSchema: z.object({
291
+ preset: preflightPresetSchema.optional().describe("Optional shortcut for common approve flows such as USDC -> escrow or USDC -> tipjar"),
292
+ action: gasQuoteActionSchema.optional().describe("Optional action to estimate and validate before sending"),
293
+ tokenAddress: addressSchema.optional().describe("Optional ERC20 token address to check"),
294
+ spender: addressSchema.optional().describe("Optional spender address for allowance checks"),
295
+ requiredAmount: z.string().optional().describe("Optional base-unit integer amount to require for token balance / allowance"),
296
+ escrowId: z.string().optional().describe("Escrow ID for action-aware checks"),
297
+ deliveryHash: hashSchema.optional().describe("Delivery hash for submit_delivery checks"),
298
+ minNativeBalanceWei: z.string().optional().describe("Optional explicit ETH threshold in wei")
299
+ }).strict(),
300
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
301
+ },
302
+ async (params) => {
303
+ try {
304
+ const agent = await getAgent();
305
+ const resolved = resolveActionPreset(agent, {
306
+ action: params.action,
307
+ tokenAddress: params.tokenAddress,
308
+ spender: params.spender
309
+ }, params.preset);
310
+ const result = await agent.preflightCheck({
311
+ action: resolved.action,
312
+ tokenAddress: resolved.tokenAddress,
313
+ spender: resolved.spender,
314
+ requiredAmount: params.requiredAmount ? BigInt(params.requiredAmount) : void 0,
315
+ escrowId: params.escrowId ? BigInt(params.escrowId) : void 0,
316
+ deliveryHash: params.deliveryHash,
317
+ minNativeBalanceWei: params.minNativeBalanceWei ? BigInt(params.minNativeBalanceWei) : void 0
318
+ });
319
+ const serialized = serializeForMcp(result);
320
+ return {
321
+ content: [{ type: "text", text: serialized }],
322
+ structuredContent: { preflight: JSON.parse(serialized) }
323
+ };
324
+ } catch (error) {
325
+ return formatError(error, "preflight_check");
326
+ }
327
+ }
328
+ );
329
+ server.registerTool(
330
+ "agentpact_get_transaction_status",
331
+ {
332
+ title: "Get Transaction Status",
333
+ description: "Read the latest observable status of a transaction without waiting. Returns pending, success, reverted, or not_found.",
334
+ inputSchema: z.object({
335
+ txHash: hashSchema.describe("Transaction hash to inspect")
336
+ }).strict(),
337
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
338
+ },
339
+ async (params) => {
340
+ try {
341
+ const agent = await getAgent();
342
+ const status = await agent.getTransactionStatus(params.txHash);
343
+ const serialized = serializeForMcp(status);
344
+ return {
345
+ content: [{ type: "text", text: serialized }],
346
+ structuredContent: { transaction: JSON.parse(serialized) }
347
+ };
348
+ } catch (error) {
349
+ return formatError(error, "get_transaction_status");
350
+ }
351
+ }
352
+ );
353
+ server.registerTool(
354
+ "agentpact_get_token_allowance",
355
+ {
356
+ title: "Get Token Allowance",
357
+ description: "Read the current agent wallet's ERC20 allowance for a spender contract.",
358
+ inputSchema: z.object({
359
+ tokenAddress: addressSchema.describe("ERC20 token contract address"),
360
+ spender: addressSchema.describe("Contract or wallet allowed to spend the token")
361
+ }).strict(),
362
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
363
+ },
364
+ async (params) => {
365
+ try {
366
+ const agent = await getAgent();
367
+ const [allowance, token] = await Promise.all([
368
+ agent.getTokenAllowance(
369
+ params.tokenAddress,
370
+ params.spender
371
+ ),
372
+ agent.getTokenBalanceInfo(params.tokenAddress)
373
+ ]);
374
+ const serialized = serializeForMcp({
375
+ owner: agent.walletAddress,
376
+ spender: params.spender,
377
+ token: {
378
+ tokenAddress: token.tokenAddress,
379
+ symbol: token.symbol,
380
+ decimals: token.decimals
381
+ },
382
+ allowanceRaw: allowance,
383
+ allowanceFormatted: formatUnitsString(allowance, token.decimals)
384
+ });
385
+ return {
386
+ content: [{ type: "text", text: serialized }],
387
+ structuredContent: JSON.parse(serialized)
388
+ };
389
+ } catch (error) {
390
+ return formatError(error, "get_token_allowance");
391
+ }
392
+ }
393
+ );
394
+ server.registerTool(
395
+ "agentpact_approve_token",
396
+ {
397
+ title: "Approve Token",
398
+ description: "Submit an ERC20 approve transaction from the current agent wallet. Exact mode expects a base-unit integer string.",
399
+ inputSchema: z.object({
400
+ tokenAddress: addressSchema.describe("ERC20 token contract address"),
401
+ spender: addressSchema.describe("Contract or wallet allowed to spend the token"),
402
+ mode: z.enum(["max", "exact"]).default("max").describe("Use 'max' for unlimited approval, or 'exact' to approve the provided base-unit amount"),
403
+ amount: z.string().optional().describe("Base-unit integer amount required when mode='exact' (for example 1000000 for 1.0 USDC)")
404
+ }).strict()
405
+ },
406
+ async (params) => {
407
+ try {
408
+ let amount;
409
+ if (params.mode === "exact") {
410
+ if (!params.amount) {
411
+ throw new Error("amount is required when mode='exact'");
412
+ }
413
+ amount = BigInt(params.amount);
414
+ }
415
+ const agent = await getAgent();
416
+ const txHash = await agent.approveToken(
417
+ params.tokenAddress,
418
+ params.spender,
419
+ amount
420
+ );
421
+ return {
422
+ content: [{
423
+ type: "text",
424
+ text: `Approval transaction submitted. TX: ${txHash}`
425
+ }],
426
+ structuredContent: {
427
+ txHash,
428
+ mode: params.mode,
429
+ amount: amount?.toString() ?? "max",
430
+ tokenAddress: params.tokenAddress,
431
+ spender: params.spender
432
+ }
433
+ };
434
+ } catch (error) {
435
+ return formatError(error, "approve_token");
436
+ }
437
+ }
438
+ );
439
+ server.registerTool(
440
+ "agentpact_wait_for_transaction",
441
+ {
442
+ title: "Wait For Transaction",
443
+ description: "Wait for a transaction receipt and return status, gas usage, and explorer link.",
444
+ inputSchema: z.object({
445
+ txHash: hashSchema.describe("Transaction hash to wait for"),
446
+ confirmations: z.number().int().min(1).max(25).default(1).describe("How many confirmations to wait for"),
447
+ timeoutMs: z.number().int().min(1e3).max(6e5).optional().describe("Optional timeout in milliseconds")
448
+ }).strict()
449
+ },
450
+ async (params) => {
451
+ try {
452
+ const agent = await getAgent();
453
+ const receipt = await agent.waitForTransaction(
454
+ params.txHash,
455
+ {
456
+ confirmations: params.confirmations,
457
+ timeoutMs: params.timeoutMs
458
+ }
459
+ );
460
+ const serialized = serializeForMcp(receipt);
461
+ return {
462
+ content: [{ type: "text", text: serialized }],
463
+ structuredContent: { receipt: JSON.parse(serialized) }
464
+ };
465
+ } catch (error) {
466
+ return formatError(error, "wait_for_transaction");
467
+ }
468
+ }
469
+ );
142
470
  server.registerTool(
143
471
  "agentpact_bid_on_task",
144
472
  {
@@ -345,11 +673,7 @@ server.registerTool(
345
673
  try {
346
674
  const agent = await getAgent();
347
675
  const escrow = await agent.client.getEscrow(BigInt(params.escrowId));
348
- const serialized = JSON.stringify(
349
- escrow,
350
- (_, v) => typeof v === "bigint" ? v.toString() + "n" : v,
351
- 2
352
- );
676
+ const serialized = serializeForMcp(escrow);
353
677
  return {
354
678
  content: [{ type: "text", text: serialized }],
355
679
  structuredContent: { escrow: JSON.parse(serialized) }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentpactai/mcp-server",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Primary MCP tool layer for AgentPact, built on top of @agentpactai/runtime.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -43,7 +43,7 @@
43
43
  "@modelcontextprotocol/sdk": "^1.27.1",
44
44
  "zod": "^4.3.6",
45
45
  "zod-to-json-schema": "^3.25.1",
46
- "@agentpactai/runtime": "0.1.6"
46
+ "@agentpactai/runtime": "0.1.7"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^25.3.5",