@haven_ai/mcp 0.0.0-dev.202609061037.7cf43bb → 0.0.0-dev.202609061923.f3d53db
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 +16 -0
- package/dist/cli.cjs +69 -14
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +69 -14
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +69 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +69 -14
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -110,6 +110,22 @@ Environment variable form:
|
|
|
110
110
|
- `haven_submit_catalog_entry`
|
|
111
111
|
- `haven_list_receipts`
|
|
112
112
|
|
|
113
|
+
### `idempotencyKey` is deprecated — send `idempotency_key`
|
|
114
|
+
|
|
115
|
+
The tools that take an idempotency key (`haven_send`, `haven_pay_mcp_tool`,
|
|
116
|
+
`haven_quote_x402`, `haven_pay_x402_quote`, `haven_pay_x402`) now accept
|
|
117
|
+
**`idempotency_key`**, the spelling the hosted Haven MCP surface and every other
|
|
118
|
+
Haven wire contract use. `idempotencyKey` still works and returns a deprecation
|
|
119
|
+
warning; it will be removed in a future release.
|
|
120
|
+
|
|
121
|
+
Send **one** of them. Sending both with different values is refused
|
|
122
|
+
(`AMBIGUOUS_IDEMPOTENCY_KEY`) with nothing contacted or spent — the key decides
|
|
123
|
+
whether a retry is the same payment or a second one, so Haven will not guess
|
|
124
|
+
which scope you meant. Sending both with the same value is fine.
|
|
125
|
+
|
|
126
|
+
The warning arrives in an optional `warnings` array on the success result. It is
|
|
127
|
+
additive: a caller that ignores it sees the response it always saw.
|
|
128
|
+
|
|
113
129
|
## First-launch consent
|
|
114
130
|
|
|
115
131
|
The first time the MCP server runs against a credential file it refuses to
|
package/dist/cli.cjs
CHANGED
|
@@ -222,12 +222,16 @@ var toolSchemas = {
|
|
|
222
222
|
asset: v3.z.enum(["ETH", "USDC"]),
|
|
223
223
|
recipient: v3.z.string().min(1),
|
|
224
224
|
amount: v3.z.string().min(1),
|
|
225
|
+
idempotency_key: v3.z.string().optional(),
|
|
226
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
225
227
|
idempotencyKey: v3.z.string().optional()
|
|
226
228
|
},
|
|
227
229
|
haven_pay_mcp_tool: {
|
|
228
230
|
merchant_url: v3.z.string().url(),
|
|
229
231
|
tool_name: v3.z.string().min(1),
|
|
230
232
|
arguments: v3.z.record(v3.z.string(), v3.z.unknown()).optional(),
|
|
233
|
+
idempotency_key: v3.z.string().optional(),
|
|
234
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
231
235
|
idempotencyKey: v3.z.string().optional()
|
|
232
236
|
},
|
|
233
237
|
haven_quote_x402: {
|
|
@@ -235,10 +239,14 @@ var toolSchemas = {
|
|
|
235
239
|
method: v3.z.string().optional(),
|
|
236
240
|
headers: headersSchema,
|
|
237
241
|
body: v3.z.string().optional(),
|
|
242
|
+
idempotency_key: v3.z.string().optional(),
|
|
243
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
238
244
|
idempotencyKey: v3.z.string().optional()
|
|
239
245
|
},
|
|
240
246
|
haven_pay_x402_quote: {
|
|
241
247
|
quote: v3.z.unknown(),
|
|
248
|
+
idempotency_key: v3.z.string().optional(),
|
|
249
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
242
250
|
idempotencyKey: v3.z.string().optional()
|
|
243
251
|
},
|
|
244
252
|
haven_pay_x402: {
|
|
@@ -246,6 +254,8 @@ var toolSchemas = {
|
|
|
246
254
|
method: v3.z.string().optional(),
|
|
247
255
|
headers: headersSchema,
|
|
248
256
|
body: v3.z.string().optional(),
|
|
257
|
+
idempotency_key: v3.z.string().optional(),
|
|
258
|
+
/** Legacy spelling, accepted during the #2366 window. Warns; do not use. */
|
|
249
259
|
idempotencyKey: v3.z.string().optional()
|
|
250
260
|
},
|
|
251
261
|
haven_resume_x402_payment: {
|
|
@@ -298,8 +308,10 @@ var toolDescriptions = {
|
|
|
298
308
|
function createToolHandlers(haven) {
|
|
299
309
|
return {
|
|
300
310
|
haven_send: async (input) => {
|
|
311
|
+
const pf = preflight("haven_send", input);
|
|
312
|
+
if ("success" in pf) return pf;
|
|
313
|
+
const { args, warnings } = pf;
|
|
301
314
|
return runTool(async () => {
|
|
302
|
-
const args = objectInput("haven_send", input);
|
|
303
315
|
try {
|
|
304
316
|
const result = await haven.pay({
|
|
305
317
|
token: args.asset,
|
|
@@ -307,7 +319,7 @@ function createToolHandlers(haven) {
|
|
|
307
319
|
to: args.recipient,
|
|
308
320
|
// #1207: was accepted by the schema but silently dropped — now
|
|
309
321
|
// carried to the backend's replay contract.
|
|
310
|
-
idempotencyKey:
|
|
322
|
+
idempotencyKey: args.idempotencyKey
|
|
311
323
|
});
|
|
312
324
|
return {
|
|
313
325
|
payment_id: result.paymentId,
|
|
@@ -331,11 +343,13 @@ function createToolHandlers(haven) {
|
|
|
331
343
|
}
|
|
332
344
|
throw err;
|
|
333
345
|
}
|
|
334
|
-
});
|
|
346
|
+
}, warnings);
|
|
335
347
|
},
|
|
336
348
|
haven_pay_mcp_tool: async (input) => {
|
|
349
|
+
const pf = preflight("haven_pay_mcp_tool", input);
|
|
350
|
+
if ("success" in pf) return pf;
|
|
351
|
+
const { args, warnings } = pf;
|
|
337
352
|
return runTool(async () => {
|
|
338
|
-
const args = objectInput("haven_pay_mcp_tool", input);
|
|
339
353
|
const envelope = buildMcpToolsCallEnvelope(args.tool_name, args.arguments);
|
|
340
354
|
const init = {
|
|
341
355
|
method: "POST",
|
|
@@ -366,18 +380,23 @@ function createToolHandlers(haven) {
|
|
|
366
380
|
merchant_url: merchantUrl,
|
|
367
381
|
...merchantUrl !== args.merchant_url ? { merchant_url_discovered_from: args.merchant_url } : {}
|
|
368
382
|
};
|
|
369
|
-
});
|
|
383
|
+
}, warnings);
|
|
370
384
|
},
|
|
371
385
|
haven_quote_x402: async (input) => {
|
|
372
|
-
const
|
|
386
|
+
const pf = preflight("haven_quote_x402", input);
|
|
387
|
+
if ("success" in pf) return pf;
|
|
388
|
+
const { args, warnings } = pf;
|
|
373
389
|
try {
|
|
374
|
-
|
|
390
|
+
const data = await haven.quoteX402(args.url, requestInit(args), { idempotencyKey: args.idempotencyKey });
|
|
391
|
+
return warnings.length > 0 ? { success: true, data, warnings } : { success: true, data };
|
|
375
392
|
} catch (err) {
|
|
376
393
|
return normalizeError(err);
|
|
377
394
|
}
|
|
378
395
|
},
|
|
379
396
|
haven_pay_x402_quote: async (input) => {
|
|
380
|
-
const
|
|
397
|
+
const pf = preflight("haven_pay_x402_quote", input);
|
|
398
|
+
if ("success" in pf) return pf;
|
|
399
|
+
const { args, warnings } = pf;
|
|
381
400
|
const quote = args.quote;
|
|
382
401
|
if (!quote || typeof quote !== "object") {
|
|
383
402
|
return wrongTool(
|
|
@@ -396,14 +415,16 @@ function createToolHandlers(haven) {
|
|
|
396
415
|
return runTool(async () => {
|
|
397
416
|
const response = await haven.payX402Quote(args.quote, { idempotencyKey: args.idempotencyKey });
|
|
398
417
|
return responsePayload(response);
|
|
399
|
-
});
|
|
418
|
+
}, warnings);
|
|
400
419
|
},
|
|
401
420
|
haven_pay_x402: async (input) => {
|
|
402
|
-
const
|
|
421
|
+
const pf = preflight("haven_pay_x402", input);
|
|
422
|
+
if ("success" in pf) return pf;
|
|
423
|
+
const { args, warnings } = pf;
|
|
403
424
|
return runTool(async () => {
|
|
404
425
|
const response = await haven.fetch(args.url, requestInit(args), { idempotencyKey: args.idempotencyKey });
|
|
405
426
|
return responsePayload(response);
|
|
406
|
-
});
|
|
427
|
+
}, warnings);
|
|
407
428
|
},
|
|
408
429
|
haven_resume_x402_payment: async (input) => {
|
|
409
430
|
const args = objectInput("haven_resume_x402_payment", input);
|
|
@@ -501,6 +522,39 @@ function isPendingApproval(status) {
|
|
|
501
522
|
function wrongTool(code, message, suggested_tool) {
|
|
502
523
|
return { success: false, code, message, suggested_tool };
|
|
503
524
|
}
|
|
525
|
+
function preflight(name, input) {
|
|
526
|
+
let args;
|
|
527
|
+
try {
|
|
528
|
+
args = objectInput(name, input);
|
|
529
|
+
} catch (err) {
|
|
530
|
+
return normalizeError(err);
|
|
531
|
+
}
|
|
532
|
+
const idem = resolveIdempotencyKey(args);
|
|
533
|
+
if ("success" in idem) return idem;
|
|
534
|
+
if (idem.key !== void 0) args = { ...args, idempotencyKey: idem.key };
|
|
535
|
+
return { args, warnings: idem.warnings };
|
|
536
|
+
}
|
|
537
|
+
function resolveIdempotencyKey(args) {
|
|
538
|
+
const modern = typeof args.idempotency_key === "string" ? args.idempotency_key : void 0;
|
|
539
|
+
const legacy = typeof args.idempotencyKey === "string" ? args.idempotencyKey : void 0;
|
|
540
|
+
if (modern !== void 0 && legacy !== void 0 && modern !== legacy) {
|
|
541
|
+
return {
|
|
542
|
+
success: false,
|
|
543
|
+
code: "AMBIGUOUS_IDEMPOTENCY_KEY",
|
|
544
|
+
message: "Both idempotency_key and idempotencyKey were sent with different values. Nothing was contacted or spent. Send exactly one \u2014 idempotency_key is the current spelling; idempotencyKey is deprecated and will be removed."
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
if (modern !== void 0) return { key: modern, warnings: [] };
|
|
548
|
+
if (legacy !== void 0) {
|
|
549
|
+
return {
|
|
550
|
+
key: legacy,
|
|
551
|
+
warnings: [
|
|
552
|
+
"idempotencyKey is deprecated and will be removed in a future release of @haven_ai/mcp. Send idempotency_key instead \u2014 it is the spelling the hosted Haven MCP surface and every other Haven wire contract use."
|
|
553
|
+
]
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
return { warnings: [] };
|
|
557
|
+
}
|
|
504
558
|
function buildMcpToolsCallEnvelope(toolName, args) {
|
|
505
559
|
return {
|
|
506
560
|
jsonrpc: "2.0",
|
|
@@ -523,9 +577,10 @@ function requestInit(input) {
|
|
|
523
577
|
body: input.body
|
|
524
578
|
};
|
|
525
579
|
}
|
|
526
|
-
async function runTool(fn) {
|
|
580
|
+
async function runTool(fn, warnings = []) {
|
|
527
581
|
try {
|
|
528
|
-
|
|
582
|
+
const data = await fn();
|
|
583
|
+
return warnings.length > 0 ? { success: true, data, warnings } : { success: true, data };
|
|
529
584
|
} catch (err) {
|
|
530
585
|
return normalizeError(err);
|
|
531
586
|
}
|
|
@@ -796,7 +851,7 @@ async function resolveHavenClient(options = {}) {
|
|
|
796
851
|
return { client, credentials };
|
|
797
852
|
}
|
|
798
853
|
var MCP_NAME = "@haven_ai/mcp";
|
|
799
|
-
var MCP_VERSION = "0.0.0-dev.
|
|
854
|
+
var MCP_VERSION = "0.0.0-dev.202609061923.f3d53db";
|
|
800
855
|
var MCP_INSTRUCTIONS = [
|
|
801
856
|
"Haven local MCP server: signs in-process with the delegate key it holds on",
|
|
802
857
|
"this machine \u2014 the key never leaves this process. Call haven_get_agent",
|