@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.
- package/README.md +31 -0
- package/dist/index.js +329 -5
- 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 =
|
|
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.
|
|
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.
|
|
46
|
+
"@agentpactai/runtime": "0.1.7"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/node": "^25.3.5",
|