@hpp-io/x402-mcp-bridge 0.0.2 → 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/README.md +146 -123
- package/bin/hpp-x402.js +5 -0
- package/dist/a2a.d.ts +2 -2
- package/dist/a2a.js +14 -6
- package/dist/a2a.js.map +1 -1
- package/dist/autoTopup.d.ts +4 -1
- package/dist/autoTopup.js +4 -0
- package/dist/autoTopup.js.map +1 -1
- package/dist/cli/channel.d.ts +1 -1
- package/dist/cli/channel.js +1 -8
- package/dist/cli/channel.js.map +1 -1
- package/dist/cli/hpp-x402.d.ts +2 -0
- package/dist/cli/hpp-x402.js +377 -0
- package/dist/cli/hpp-x402.js.map +1 -0
- package/dist/cli/install-claude-code.d.ts +24 -0
- package/dist/cli/install-claude-code.js +50 -0
- package/dist/cli/install-claude-code.js.map +1 -0
- package/dist/cli/install-cursor.d.ts +7 -0
- package/dist/cli/install-cursor.js +26 -0
- package/dist/cli/install-cursor.js.map +1 -0
- package/dist/cli/install-mcp-host.d.ts +2 -2
- package/dist/cli/install-mcp-host.js.map +1 -1
- package/dist/cli/install-windsurf.d.ts +7 -0
- package/dist/cli/install-windsurf.js +37 -0
- package/dist/cli/install-windsurf.js.map +1 -0
- package/dist/cli/policy.d.ts +1 -1
- package/dist/cli/policy.js +1 -8
- package/dist/cli/policy.js.map +1 -1
- package/dist/cli/revoke.d.ts +1 -1
- package/dist/cli/revoke.js +1 -5
- package/dist/cli/revoke.js.map +1 -1
- package/dist/cli/safe.d.ts +62 -62
- package/dist/cli/serve.d.ts +1 -0
- package/dist/cli/serve.js +128 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +1 -5
- package/dist/cli/setup.js.map +1 -1
- package/dist/client.d.ts +6 -2
- package/dist/client.js +34 -15
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +71 -15
- package/dist/config.js +66 -10
- package/dist/config.js.map +1 -1
- package/dist/discovery.d.ts +43 -0
- package/dist/discovery.js +62 -0
- package/dist/discovery.js.map +1 -0
- package/dist/discoveryTools.d.ts +75 -0
- package/dist/discoveryTools.js +101 -0
- package/dist/discoveryTools.js.map +1 -0
- package/dist/funds/direct-balance.d.ts +28 -0
- package/dist/funds/direct-balance.js +61 -0
- package/dist/funds/direct-balance.js.map +1 -0
- package/dist/funds.d.ts +32 -0
- package/dist/funds.js +2 -0
- package/dist/funds.js.map +1 -0
- package/dist/httpX402.d.ts +8 -2
- package/dist/httpX402.js +26 -13
- package/dist/httpX402.js.map +1 -1
- package/dist/index.js +66 -11
- package/dist/index.js.map +1 -1
- package/dist/sellerTools.d.ts +247 -0
- package/dist/sellerTools.js +202 -0
- package/dist/sellerTools.js.map +1 -0
- package/dist/server.d.ts +8 -2
- package/dist/server.js +165 -64
- package/dist/server.js.map +1 -1
- package/dist/spendGuard.d.ts +24 -0
- package/dist/spendGuard.js +124 -0
- package/dist/spendGuard.js.map +1 -0
- package/package.json +13 -12
- package/bin/hpp-x402-channel.js +0 -5
- package/bin/hpp-x402-keychain.js +0 -5
- package/bin/hpp-x402-policy.js +0 -5
- package/bin/hpp-x402-safe-revoke.js +0 -5
- package/bin/hpp-x402-safe-setup.js +0 -5
- package/dist/autoSettlePickup.d.ts +0 -69
- package/dist/autoSettlePickup.js +0 -150
- package/dist/autoSettlePickup.js.map +0 -1
- package/dist/cli/keychain.d.ts +0 -1
- package/dist/cli/keychain.js +0 -147
- package/dist/cli/keychain.js.map +0 -1
package/dist/client.js
CHANGED
|
@@ -12,6 +12,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
12
12
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
13
13
|
import { wrapMCPClientWithPaymentFromConfig } from "@x402/mcp";
|
|
14
14
|
import { ExactEvmScheme } from "@x402/evm/exact/client";
|
|
15
|
+
import { UptoEvmScheme } from "@x402/evm/upto/client";
|
|
15
16
|
import { BatchSettlementEvmScheme, processSettleResponse, } from "@x402/evm/batch-settlement/client";
|
|
16
17
|
// @x402/evm 2.13.0 moved FileClientChannelStorage into its own subpath.
|
|
17
18
|
import { FileClientChannelStorage } from "@x402/evm/batch-settlement/client/file-storage";
|
|
@@ -45,10 +46,9 @@ export async function connectUpstream(opts) {
|
|
|
45
46
|
// it; the UpstreamClient surface reads it.
|
|
46
47
|
let lastPaymentAmountAtomic = null;
|
|
47
48
|
const x402 = wrapMCPClientWithPaymentFromConfig(base, {
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
// why it picked).
|
|
49
|
+
// Register all three client schemes so the bridge can pay whatever a
|
|
50
|
+
// service advertises. The selector (below) honors the seller's accepts
|
|
51
|
+
// order and logs the choice; registration order here is not significant.
|
|
52
52
|
schemes: [
|
|
53
53
|
{
|
|
54
54
|
network: opts.network,
|
|
@@ -60,17 +60,31 @@ export async function connectUpstream(opts) {
|
|
|
60
60
|
network: opts.network,
|
|
61
61
|
client: new ExactEvmScheme(opts.signer.viemAccount),
|
|
62
62
|
},
|
|
63
|
+
{
|
|
64
|
+
// upto (usage-based) — selected when the service advertises it first
|
|
65
|
+
// (seller-driven). The client auto-detects the facilitator's EIP-2612
|
|
66
|
+
// gas-sponsoring extension and signs the Permit2 permit accordingly;
|
|
67
|
+
// without it the payer must have an existing approve(Permit2).
|
|
68
|
+
// Ref: x402-upto-scheme design/05.
|
|
69
|
+
network: opts.network,
|
|
70
|
+
// rpcUrl lets the upto client read the EIP-2612 token nonce so it can
|
|
71
|
+
// sign the gasless Permit2 approval (no on-chain approve needed).
|
|
72
|
+
client: new UptoEvmScheme(opts.signer.viemAccount, { rpcUrl: opts.rpcUrl }),
|
|
73
|
+
},
|
|
63
74
|
],
|
|
64
75
|
paymentRequirementsSelector: (_x402Version, accepts) => {
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
76
|
+
// Honor the SELLER's advertised order: pick the first accept whose
|
|
77
|
+
// scheme this client can sign. Scheme choice is a property of the
|
|
78
|
+
// service's pricing model (seller advertises priority via accepts
|
|
79
|
+
// order), NOT buyer config — so a usage-based service that lists `upto`
|
|
80
|
+
// first gets upto automatically; a fixed-price service that lists
|
|
81
|
+
// batch/exact gets those. `HPP_X402_PREFER_EXACT=true` is a demo-only
|
|
82
|
+
// override (forces exact, e.g. to show wallet balance deltas live).
|
|
83
|
+
const supported = new Set(["exact", "batch-settlement", "upto"]);
|
|
84
|
+
let picked = accepts.find((a) => supported.has(a.scheme)) ?? accepts[0];
|
|
85
|
+
if (process.env.HPP_X402_PREFER_EXACT === "true") {
|
|
86
|
+
picked = accepts.find((a) => a.scheme === "exact") ?? picked;
|
|
87
|
+
}
|
|
74
88
|
const amountStr = picked.amount;
|
|
75
89
|
if (amountStr) {
|
|
76
90
|
try {
|
|
@@ -90,7 +104,12 @@ export async function connectUpstream(opts) {
|
|
|
90
104
|
}, {
|
|
91
105
|
autoPayment: true,
|
|
92
106
|
onPaymentRequested: async ({ paymentRequired }) => {
|
|
93
|
-
|
|
107
|
+
// A multi-network resource-server advertises accepts for several networks;
|
|
108
|
+
// pick THIS bridge's network so the topup amount + log match the accept the
|
|
109
|
+
// selector will actually settle (the SDK filters accepts by registered
|
|
110
|
+
// network). Falling back to accepts[0] keeps single-network servers working.
|
|
111
|
+
const accept = paymentRequired.accepts?.find((a) => a.network === opts.network) ??
|
|
112
|
+
paymentRequired.accepts?.[0];
|
|
94
113
|
if (!accept)
|
|
95
114
|
return false;
|
|
96
115
|
const requiredAtomic = BigInt(accept.amount ?? "0");
|
|
@@ -100,7 +119,7 @@ export async function connectUpstream(opts) {
|
|
|
100
119
|
network: accept.network,
|
|
101
120
|
});
|
|
102
121
|
try {
|
|
103
|
-
const txHash = await opts.
|
|
122
|
+
const txHash = await opts.funds.ensure(requiredAtomic);
|
|
104
123
|
if (txHash) {
|
|
105
124
|
log.info("autoTopup.executed", { txHash, requiredAtomic: requiredAtomic.toString() });
|
|
106
125
|
}
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,kCAAkC,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EACL,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,mCAAmC,CAAC;AAC3C,wEAAwE;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gDAAgD,CAAC;AAK1F,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B;;;;;;;;;GASG;AACH,MAAM,oBAAoB,GACxB,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -5,42 +5,98 @@
|
|
|
5
5
|
* loudly at startup rather than mid-call.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
declare const Schema: z.ZodObject<{
|
|
8
|
+
declare const Schema: z.ZodEffects<z.ZodObject<{
|
|
9
9
|
DELEGATE_PRIVATE_KEY: z.ZodEffects<z.ZodString, string, string>;
|
|
10
|
-
SAFE_ADDRESS: z.ZodString
|
|
11
|
-
ALLOWANCE_MODULE_ADDRESS: z.ZodString
|
|
12
|
-
USDCE_ADDRESS: z.ZodString
|
|
10
|
+
SAFE_ADDRESS: z.ZodOptional<z.ZodString>;
|
|
11
|
+
ALLOWANCE_MODULE_ADDRESS: z.ZodOptional<z.ZodString>;
|
|
12
|
+
USDCE_ADDRESS: z.ZodOptional<z.ZodString>;
|
|
13
13
|
RESOURCE_SERVER_URL: z.ZodOptional<z.ZodString>;
|
|
14
|
-
HPP_RPC_URL: z.ZodString
|
|
15
|
-
HPP_NETWORK: z.ZodString
|
|
14
|
+
HPP_RPC_URL: z.ZodOptional<z.ZodString>;
|
|
15
|
+
HPP_NETWORK: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
16
16
|
TOPUP_AMOUNT_ATOMIC: z.ZodOptional<z.ZodString>;
|
|
17
17
|
TOPUP_HEADROOM_X: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
18
18
|
LOG_LEVEL: z.ZodDefault<z.ZodOptional<z.ZodEnum<["off", "info", "debug"]>>>;
|
|
19
|
+
HPP_X402_DISCOVERY: z.ZodDefault<z.ZodOptional<z.ZodEnum<["on", "off"]>>>;
|
|
20
|
+
HPP_X402_DISCOVERY_URL: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
21
|
+
HPP_X402_SELLER: z.ZodDefault<z.ZodOptional<z.ZodEnum<["on", "off"]>>>;
|
|
22
|
+
HPP_X402_FACILITATOR_URL: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
19
23
|
}, "strip", z.ZodTypeAny, {
|
|
20
24
|
DELEGATE_PRIVATE_KEY: string;
|
|
21
|
-
SAFE_ADDRESS: string;
|
|
22
|
-
ALLOWANCE_MODULE_ADDRESS: string;
|
|
23
|
-
USDCE_ADDRESS: string;
|
|
24
|
-
HPP_RPC_URL: string;
|
|
25
25
|
HPP_NETWORK: string;
|
|
26
26
|
TOPUP_HEADROOM_X: string;
|
|
27
27
|
LOG_LEVEL: "off" | "info" | "debug";
|
|
28
|
+
HPP_X402_DISCOVERY: "off" | "on";
|
|
29
|
+
HPP_X402_DISCOVERY_URL: string;
|
|
30
|
+
HPP_X402_SELLER: "off" | "on";
|
|
31
|
+
HPP_X402_FACILITATOR_URL: string;
|
|
32
|
+
SAFE_ADDRESS?: string | undefined;
|
|
33
|
+
ALLOWANCE_MODULE_ADDRESS?: string | undefined;
|
|
34
|
+
USDCE_ADDRESS?: string | undefined;
|
|
28
35
|
RESOURCE_SERVER_URL?: string | undefined;
|
|
36
|
+
HPP_RPC_URL?: string | undefined;
|
|
29
37
|
TOPUP_AMOUNT_ATOMIC?: string | undefined;
|
|
30
38
|
}, {
|
|
31
39
|
DELEGATE_PRIVATE_KEY: string;
|
|
32
|
-
SAFE_ADDRESS
|
|
33
|
-
ALLOWANCE_MODULE_ADDRESS
|
|
34
|
-
USDCE_ADDRESS
|
|
35
|
-
|
|
40
|
+
SAFE_ADDRESS?: string | undefined;
|
|
41
|
+
ALLOWANCE_MODULE_ADDRESS?: string | undefined;
|
|
42
|
+
USDCE_ADDRESS?: string | undefined;
|
|
43
|
+
RESOURCE_SERVER_URL?: string | undefined;
|
|
44
|
+
HPP_RPC_URL?: string | undefined;
|
|
45
|
+
HPP_NETWORK?: string | undefined;
|
|
46
|
+
TOPUP_AMOUNT_ATOMIC?: string | undefined;
|
|
47
|
+
TOPUP_HEADROOM_X?: string | undefined;
|
|
48
|
+
LOG_LEVEL?: "off" | "info" | "debug" | undefined;
|
|
49
|
+
HPP_X402_DISCOVERY?: "off" | "on" | undefined;
|
|
50
|
+
HPP_X402_DISCOVERY_URL?: string | undefined;
|
|
51
|
+
HPP_X402_SELLER?: "off" | "on" | undefined;
|
|
52
|
+
HPP_X402_FACILITATOR_URL?: string | undefined;
|
|
53
|
+
}>, {
|
|
54
|
+
DELEGATE_PRIVATE_KEY: string;
|
|
36
55
|
HPP_NETWORK: string;
|
|
56
|
+
TOPUP_HEADROOM_X: string;
|
|
57
|
+
LOG_LEVEL: "off" | "info" | "debug";
|
|
58
|
+
HPP_X402_DISCOVERY: "off" | "on";
|
|
59
|
+
HPP_X402_DISCOVERY_URL: string;
|
|
60
|
+
HPP_X402_SELLER: "off" | "on";
|
|
61
|
+
HPP_X402_FACILITATOR_URL: string;
|
|
62
|
+
SAFE_ADDRESS?: string | undefined;
|
|
63
|
+
ALLOWANCE_MODULE_ADDRESS?: string | undefined;
|
|
64
|
+
USDCE_ADDRESS?: string | undefined;
|
|
65
|
+
RESOURCE_SERVER_URL?: string | undefined;
|
|
66
|
+
HPP_RPC_URL?: string | undefined;
|
|
67
|
+
TOPUP_AMOUNT_ATOMIC?: string | undefined;
|
|
68
|
+
}, {
|
|
69
|
+
DELEGATE_PRIVATE_KEY: string;
|
|
70
|
+
SAFE_ADDRESS?: string | undefined;
|
|
71
|
+
ALLOWANCE_MODULE_ADDRESS?: string | undefined;
|
|
72
|
+
USDCE_ADDRESS?: string | undefined;
|
|
37
73
|
RESOURCE_SERVER_URL?: string | undefined;
|
|
74
|
+
HPP_RPC_URL?: string | undefined;
|
|
75
|
+
HPP_NETWORK?: string | undefined;
|
|
38
76
|
TOPUP_AMOUNT_ATOMIC?: string | undefined;
|
|
39
77
|
TOPUP_HEADROOM_X?: string | undefined;
|
|
40
78
|
LOG_LEVEL?: "off" | "info" | "debug" | undefined;
|
|
79
|
+
HPP_X402_DISCOVERY?: "off" | "on" | undefined;
|
|
80
|
+
HPP_X402_DISCOVERY_URL?: string | undefined;
|
|
81
|
+
HPP_X402_SELLER?: "off" | "on" | undefined;
|
|
82
|
+
HPP_X402_FACILITATOR_URL?: string | undefined;
|
|
41
83
|
}>;
|
|
42
|
-
export type Config = z.infer<typeof Schema> & {
|
|
84
|
+
export type Config = Omit<z.infer<typeof Schema>, "USDCE_ADDRESS" | "HPP_RPC_URL"> & {
|
|
85
|
+
/** Filled from NETWORK_DEFAULTS when omitted, so always present downstream. */
|
|
86
|
+
USDCE_ADDRESS: string;
|
|
87
|
+
HPP_RPC_URL: string;
|
|
43
88
|
chainId: number;
|
|
89
|
+
/** "safe" when SAFE_ADDRESS + ALLOWANCE_MODULE_ADDRESS are set (autoTopup
|
|
90
|
+
* from the Safe); "light" when both are omitted (delegate holds USDC.e). */
|
|
91
|
+
walletMode: "safe" | "light";
|
|
92
|
+
/** true when HPP_X402_DISCOVERY === "on" — register hpp_discover/hpp_call. */
|
|
93
|
+
discoveryEnabled: boolean;
|
|
94
|
+
/** Base URL of the discovery REST API. */
|
|
95
|
+
discoveryUrl: string;
|
|
96
|
+
/** true when HPP_X402_SELLER === "on" — register seller_* tools. */
|
|
97
|
+
sellerEnabled: boolean;
|
|
98
|
+
/** Facilitator base URL used by seller verify/settle. */
|
|
99
|
+
facilitatorUrl: string;
|
|
44
100
|
};
|
|
45
101
|
export declare function loadConfig(env?: NodeJS.ProcessEnv): Config;
|
|
46
102
|
export {};
|
package/dist/config.js
CHANGED
|
@@ -8,6 +8,11 @@ import { z } from "zod";
|
|
|
8
8
|
const HEX_ADDR = /^0x[0-9a-fA-F]{40}$/;
|
|
9
9
|
const HEX_KEY = /^0x[0-9a-fA-F]{64}$/;
|
|
10
10
|
const KEYCHAIN_URI = /^keychain:\/\/[^\/]+\/[a-zA-Z0-9._-]+$/;
|
|
11
|
+
// Per-network defaults so USDCE_ADDRESS / HPP_RPC_URL can be omitted (zero-config).
|
|
12
|
+
const NETWORK_DEFAULTS = {
|
|
13
|
+
"eip155:181228": { rpc: "https://sepolia.hpp.io", usdc: "0x401eCb1D350407f13ba348573E5630B83638E30D" },
|
|
14
|
+
"eip155:190415": { rpc: "https://mainnet.hpp.io", usdc: "0x401eCb1D350407f13ba348573E5630B83638E30D" },
|
|
15
|
+
};
|
|
11
16
|
const Schema = z.object({
|
|
12
17
|
// Delegate EOA — signs EIP-3009 payments + executeAllowanceTransfer.
|
|
13
18
|
// Accepted forms:
|
|
@@ -16,21 +21,25 @@ const Schema = z.object({
|
|
|
16
21
|
DELEGATE_PRIVATE_KEY: z
|
|
17
22
|
.string()
|
|
18
23
|
.refine((v) => HEX_KEY.test(v) || KEYCHAIN_URI.test(v), "expected 0x + 64 hex chars OR keychain://hpp-x402/<account>"),
|
|
19
|
-
// Safe wallet that holds the user's USDC.e.
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
//
|
|
24
|
-
|
|
24
|
+
// Safe wallet that holds the user's USDC.e (Safe mode only). Omit for light
|
|
25
|
+
// mode, where the delegate EOA holds USDC.e directly. Must be set together
|
|
26
|
+
// with ALLOWANCE_MODULE_ADDRESS (both-or-neither, enforced below).
|
|
27
|
+
SAFE_ADDRESS: z.string().regex(HEX_ADDR).optional(),
|
|
28
|
+
// Deployed AllowanceModule (Safe mode only; pairs with SAFE_ADDRESS).
|
|
29
|
+
ALLOWANCE_MODULE_ADDRESS: z.string().regex(HEX_ADDR).optional(),
|
|
30
|
+
// Asset paid in (USDC.e on HPP). Optional — defaults per network (below).
|
|
31
|
+
USDCE_ADDRESS: z.string().regex(HEX_ADDR).optional(),
|
|
25
32
|
// Remote MCP server we proxy to (the seller). Optional: when unset the
|
|
26
33
|
// bridge runs in local-tools-only mode (e.g. credit top-up / A2A) and skips
|
|
27
34
|
// the upstream connection entirely.
|
|
28
35
|
RESOURCE_SERVER_URL: z.string().url().optional(),
|
|
29
|
-
// Chain RPC.
|
|
30
|
-
HPP_RPC_URL: z.string().url(),
|
|
36
|
+
// Chain RPC. Optional — defaults per network (below).
|
|
37
|
+
HPP_RPC_URL: z.string().url().optional(),
|
|
31
38
|
// CAIP-2 network identifier used by @x402/evm.
|
|
32
39
|
// e.g. "eip155:181228" (HPP Sepolia) / "eip155:190415" (HPP Mainnet).
|
|
33
|
-
|
|
40
|
+
// Optional — defaults to HPP Sepolia so a bare `npx @hpp-io/x402-mcp-bridge`
|
|
41
|
+
// boots with zero config (see NETWORK_DEFAULTS + runBridge auto-wallet).
|
|
42
|
+
HPP_NETWORK: z.string().regex(/^eip155:\d+$/).optional().default("eip155:181228"),
|
|
34
43
|
// Optional knobs ------------------------------------------------------
|
|
35
44
|
// How much to pull on each topup, in atomic USDC.e units. If unset,
|
|
36
45
|
// the bridge tops up "just enough" for the upcoming payment + small
|
|
@@ -49,6 +58,40 @@ const Schema = z.object({
|
|
|
49
58
|
.default("10"),
|
|
50
59
|
// Logging. "off" = silent (good for clean stdio), "debug" = verbose stderr.
|
|
51
60
|
LOG_LEVEL: z.enum(["off", "info", "debug"]).optional().default("info"),
|
|
61
|
+
// Curated service discovery (hpp-x402-discovery). "on" (default) registers
|
|
62
|
+
// the hpp_discover / hpp_call tools that query the HPP discovery directory —
|
|
63
|
+
// a facilitator-indexed, semi-curated list of paid x402 services. "off"
|
|
64
|
+
// disables them (manual RESOURCE_SERVER_URL only).
|
|
65
|
+
HPP_X402_DISCOVERY: z.enum(["on", "off"]).optional().default("on"),
|
|
66
|
+
HPP_X402_DISCOVERY_URL: z
|
|
67
|
+
.string()
|
|
68
|
+
.url()
|
|
69
|
+
.optional()
|
|
70
|
+
.default("https://x402-discovery.hpp.io"),
|
|
71
|
+
// Seller tools (A2 Phase 1). "on" registers seller_* MCP tools so this agent
|
|
72
|
+
// can charge others over x402 (facilitator verify/settle wrappers). Off by
|
|
73
|
+
// default — buyers don't need them.
|
|
74
|
+
HPP_X402_SELLER: z.enum(["on", "off"]).optional().default("off"),
|
|
75
|
+
HPP_X402_FACILITATOR_URL: z
|
|
76
|
+
.string()
|
|
77
|
+
.url()
|
|
78
|
+
.optional()
|
|
79
|
+
.default("https://facilitator-sepolia.hpp.io"),
|
|
80
|
+
})
|
|
81
|
+
// Wallet mode is inferred from Safe config presence: both set = Safe mode
|
|
82
|
+
// (autoTopup from the Safe within an on-chain cap); both omitted = light mode
|
|
83
|
+
// (delegate EOA holds USDC.e directly). Setting one without the other is a
|
|
84
|
+
// config error.
|
|
85
|
+
.superRefine((v, ctx) => {
|
|
86
|
+
const hasSafe = !!v.SAFE_ADDRESS;
|
|
87
|
+
const hasModule = !!v.ALLOWANCE_MODULE_ADDRESS;
|
|
88
|
+
if (hasSafe !== hasModule) {
|
|
89
|
+
ctx.addIssue({
|
|
90
|
+
code: z.ZodIssueCode.custom,
|
|
91
|
+
path: [hasSafe ? "ALLOWANCE_MODULE_ADDRESS" : "SAFE_ADDRESS"],
|
|
92
|
+
message: "SAFE_ADDRESS and ALLOWANCE_MODULE_ADDRESS must be set together (Safe mode) or both omitted (light mode)",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
52
95
|
});
|
|
53
96
|
export function loadConfig(env = process.env) {
|
|
54
97
|
const parsed = Schema.safeParse(env);
|
|
@@ -60,6 +103,19 @@ export function loadConfig(env = process.env) {
|
|
|
60
103
|
}
|
|
61
104
|
const v = parsed.data;
|
|
62
105
|
const chainId = Number(v.HPP_NETWORK.split(":")[1]);
|
|
63
|
-
|
|
106
|
+
const walletMode = v.SAFE_ADDRESS && v.ALLOWANCE_MODULE_ADDRESS ? "safe" : "light";
|
|
107
|
+
// Zero-config: fill USDC.e + RPC from per-network defaults when omitted.
|
|
108
|
+
const defaults = NETWORK_DEFAULTS[v.HPP_NETWORK] ?? NETWORK_DEFAULTS["eip155:181228"];
|
|
109
|
+
return {
|
|
110
|
+
...v,
|
|
111
|
+
USDCE_ADDRESS: v.USDCE_ADDRESS ?? defaults.usdc,
|
|
112
|
+
HPP_RPC_URL: v.HPP_RPC_URL ?? defaults.rpc,
|
|
113
|
+
chainId,
|
|
114
|
+
walletMode,
|
|
115
|
+
discoveryEnabled: v.HPP_X402_DISCOVERY === "on",
|
|
116
|
+
discoveryUrl: v.HPP_X402_DISCOVERY_URL,
|
|
117
|
+
sellerEnabled: v.HPP_X402_SELLER === "on",
|
|
118
|
+
facilitatorUrl: v.HPP_X402_FACILITATOR_URL,
|
|
119
|
+
};
|
|
64
120
|
}
|
|
65
121
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,QAAQ,GAAG,qBAAqB,CAAC;AACvC,MAAM,OAAO,GAAG,qBAAqB,CAAC;AACtC,MAAM,YAAY,GAAG,wCAAwC,CAAC;AAE9D,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACtB,qEAAqE;IACrE,kBAAkB;IAClB,oDAAoD;IACpD,+EAA+E;IAC/E,oBAAoB,EAAE,CAAC;SACpB,MAAM,EAAE;SACR,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAC9C,6DAA6D,CAC9D;IAEH,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface DiscoveredResource {
|
|
2
|
+
id: string;
|
|
3
|
+
type: "http" | "mcp" | "a2a";
|
|
4
|
+
resourceUrl: string;
|
|
5
|
+
routeTemplate?: string;
|
|
6
|
+
toolName?: string;
|
|
7
|
+
skillId?: string;
|
|
8
|
+
agentCardUrl?: string;
|
|
9
|
+
payTo: string;
|
|
10
|
+
network: string;
|
|
11
|
+
asset: string;
|
|
12
|
+
scheme: string;
|
|
13
|
+
priceAtomic: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
httpMethod?: string;
|
|
16
|
+
bodyType?: "json" | "form-data" | "text";
|
|
17
|
+
transport?: "streamable-http" | "sse";
|
|
18
|
+
x402Version: number;
|
|
19
|
+
}
|
|
20
|
+
export interface DiscoveredResourceDetail extends DiscoveredResource {
|
|
21
|
+
metadata?: {
|
|
22
|
+
info?: unknown;
|
|
23
|
+
schema?: unknown;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface DiscoverQuery {
|
|
27
|
+
/** Free-text semantic search; omit to browse the newest/highest-ranked. */
|
|
28
|
+
query?: string;
|
|
29
|
+
type?: "http" | "mcp" | "a2a" | "all";
|
|
30
|
+
/** CAIP-2 network filter, e.g. "eip155:190415". */
|
|
31
|
+
network?: string;
|
|
32
|
+
limit?: number;
|
|
33
|
+
}
|
|
34
|
+
export declare class DiscoveryClient {
|
|
35
|
+
private readonly baseUrl;
|
|
36
|
+
private readonly timeoutMs;
|
|
37
|
+
constructor(baseUrl: string, timeoutMs?: number);
|
|
38
|
+
private get;
|
|
39
|
+
/** List or semantically search the directory. */
|
|
40
|
+
discover(q: DiscoverQuery): Promise<DiscoveredResource[]>;
|
|
41
|
+
/** Full detail for one resource (incl. metadata.schema when present). */
|
|
42
|
+
detail(id: string): Promise<DiscoveredResourceDetail>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client for the HPP x402-discovery REST API — a curated, facilitator-indexed
|
|
3
|
+
* directory of paid x402 services on the HPP chain.
|
|
4
|
+
*
|
|
5
|
+
* Read-only from the bridge's side: we query discovery to *find* services,
|
|
6
|
+
* then pay them directly with the bridge's own wallet. Discovery never holds
|
|
7
|
+
* funds or sees our keys (non-custodial).
|
|
8
|
+
*
|
|
9
|
+
* REST contract (hpp-x402-discovery/spec/openapi.yaml → routes/discovery.ts):
|
|
10
|
+
* GET /discovery/resources?type&network&limit&offset -> { items: [...] }
|
|
11
|
+
* GET /discovery/search?q&type&network&sort&limit -> { items: [...] }
|
|
12
|
+
* GET /discovery/resources/:id -> ResourceDetail
|
|
13
|
+
*/
|
|
14
|
+
import { log } from "./log.js";
|
|
15
|
+
export class DiscoveryClient {
|
|
16
|
+
baseUrl;
|
|
17
|
+
timeoutMs;
|
|
18
|
+
constructor(baseUrl, timeoutMs = 10_000) {
|
|
19
|
+
this.baseUrl = baseUrl;
|
|
20
|
+
this.timeoutMs = timeoutMs;
|
|
21
|
+
}
|
|
22
|
+
async get(path) {
|
|
23
|
+
const url = this.baseUrl.replace(/\/$/, "") + path;
|
|
24
|
+
const ac = new AbortController();
|
|
25
|
+
const t = setTimeout(() => ac.abort(), this.timeoutMs);
|
|
26
|
+
try {
|
|
27
|
+
const res = await fetch(url, {
|
|
28
|
+
signal: ac.signal,
|
|
29
|
+
headers: { accept: "application/json" },
|
|
30
|
+
});
|
|
31
|
+
if (!res.ok)
|
|
32
|
+
throw new Error(`discovery ${res.status} for ${path}`);
|
|
33
|
+
return (await res.json());
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
clearTimeout(t);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** List or semantically search the directory. */
|
|
40
|
+
async discover(q) {
|
|
41
|
+
const type = q.type ?? "all";
|
|
42
|
+
const limit = Math.min(Math.max(q.limit ?? 20, 1), 50);
|
|
43
|
+
const params = new URLSearchParams();
|
|
44
|
+
params.set("type", type);
|
|
45
|
+
if (q.network)
|
|
46
|
+
params.set("network", q.network);
|
|
47
|
+
params.set("limit", String(limit));
|
|
48
|
+
const query = q.query?.trim();
|
|
49
|
+
const path = query
|
|
50
|
+
? `/discovery/search?q=${encodeURIComponent(query)}&${params.toString()}`
|
|
51
|
+
: `/discovery/resources?${params.toString()}`;
|
|
52
|
+
const out = await this.get(path);
|
|
53
|
+
const items = out.items ?? [];
|
|
54
|
+
log.debug("discovery.discover", { path, count: items.length });
|
|
55
|
+
return items;
|
|
56
|
+
}
|
|
57
|
+
/** Full detail for one resource (incl. metadata.schema when present). */
|
|
58
|
+
async detail(id) {
|
|
59
|
+
return this.get(`/discovery/resources/${encodeURIComponent(id)}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAmC/B,MAAM,OAAO,eAAe;IAEP;IACA;IAFnB,YACmB,OAAe,EACf,YAAY,MAAM;QADlB,YAAO,GAAP,OAAO,CAAQ;QACf,cAAS,GAAT,SAAS,CAAS;IAClC,CAAC;IAEI,KAAK,CAAC,GAAG,CAAI,IAAY;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;QACnD,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,MAAM,EAAE,EAAE,CAAC,MAAM;gBACjB,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;aACxC,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,QAAQ,IAAI,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;QACjC,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,KAAK,CAAC,QAAQ,CAAC,CAAgB;QAC7B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,OAAO;YAAE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAEnC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK;YAChB,CAAC,CAAC,uBAAuB,kBAAkB,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE;YACzE,CAAC,CAAC,wBAAwB,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAEhD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAmC,IAAI,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9B,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,yEAAyE;IACzE,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,OAAO,IAAI,CAAC,GAAG,CACb,wBAAwB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CACjD,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery-backed local tools: hpp_discover + hpp_call.
|
|
3
|
+
*
|
|
4
|
+
* The multi-service UX decision (SERVICE_CONNECTION_DESIGN §멀티서비스 UX):
|
|
5
|
+
* instead of proxying every discovered service's tools (context explosion),
|
|
6
|
+
* expose two generic tools —
|
|
7
|
+
* - hpp_discover: list/search the curated directory (read-only, no payment)
|
|
8
|
+
* - hpp_call: call one discovered service by id (payment via our wallet)
|
|
9
|
+
*
|
|
10
|
+
* hpp_call routes HTTP-typed resources through the same x402 HTTP payment path
|
|
11
|
+
* as x402_http_call, but marks the call `trustedSource` so it skips the manual
|
|
12
|
+
* host allowlist — curated discovery is the trust boundary — while keeping the
|
|
13
|
+
* daily spend cap. MCP/A2A-typed resources return connection guidance.
|
|
14
|
+
*/
|
|
15
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
16
|
+
import type { DiscoveryClient } from "./discovery.js";
|
|
17
|
+
import { type HttpX402Deps } from "./httpX402.js";
|
|
18
|
+
export declare const HPP_DISCOVER_TOOL: {
|
|
19
|
+
readonly name: "hpp_discover";
|
|
20
|
+
readonly description: string;
|
|
21
|
+
readonly inputSchema: {
|
|
22
|
+
readonly type: "object";
|
|
23
|
+
readonly properties: {
|
|
24
|
+
readonly query: {
|
|
25
|
+
readonly type: "string";
|
|
26
|
+
readonly description: "Optional free-text search over the directory.";
|
|
27
|
+
};
|
|
28
|
+
readonly type: {
|
|
29
|
+
readonly type: "string";
|
|
30
|
+
readonly enum: readonly ["http", "mcp", "a2a", "all"];
|
|
31
|
+
readonly description: "Filter by resource type (default all).";
|
|
32
|
+
};
|
|
33
|
+
readonly network: {
|
|
34
|
+
readonly type: "string";
|
|
35
|
+
readonly description: "Filter by CAIP-2 network, e.g. eip155:190415.";
|
|
36
|
+
};
|
|
37
|
+
readonly limit: {
|
|
38
|
+
readonly type: "number";
|
|
39
|
+
readonly description: "Max results (default 20, max 50).";
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
readonly additionalProperties: false;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export declare const HPP_CALL_TOOL: {
|
|
46
|
+
readonly name: "hpp_call";
|
|
47
|
+
readonly description: string;
|
|
48
|
+
readonly inputSchema: {
|
|
49
|
+
readonly type: "object";
|
|
50
|
+
readonly properties: {
|
|
51
|
+
readonly resourceId: {
|
|
52
|
+
readonly type: "string";
|
|
53
|
+
readonly description: "Service id returned by hpp_discover.";
|
|
54
|
+
};
|
|
55
|
+
readonly body: {
|
|
56
|
+
readonly type: "object";
|
|
57
|
+
readonly description: "Request body / input args for the service.";
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
readonly required: readonly ["resourceId"];
|
|
61
|
+
readonly additionalProperties: false;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
export interface DiscoverArgs {
|
|
65
|
+
query?: string;
|
|
66
|
+
type?: "http" | "mcp" | "a2a" | "all";
|
|
67
|
+
network?: string;
|
|
68
|
+
limit?: number;
|
|
69
|
+
}
|
|
70
|
+
export interface HppCallArgs {
|
|
71
|
+
resourceId: string;
|
|
72
|
+
body?: unknown;
|
|
73
|
+
}
|
|
74
|
+
export declare function hppDiscover(client: DiscoveryClient, args: DiscoverArgs): Promise<CallToolResult>;
|
|
75
|
+
export declare function hppCall(deps: HttpX402Deps, client: DiscoveryClient, args: HppCallArgs): Promise<CallToolResult>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { x402HttpCall } from "./httpX402.js";
|
|
2
|
+
export const HPP_DISCOVER_TOOL = {
|
|
3
|
+
name: "hpp_discover",
|
|
4
|
+
description: "Discover paid x402 services on the HPP chain from the curated discovery " +
|
|
5
|
+
"directory. Returns services with their resourceId, description, price " +
|
|
6
|
+
"(USDC.e atomic units), network and type. Pass `query` for a semantic " +
|
|
7
|
+
"search (e.g. 'image generation'), or omit it to browse. Then invoke one " +
|
|
8
|
+
"with hpp_call({ resourceId, body }).",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
query: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Optional free-text search over the directory.",
|
|
15
|
+
},
|
|
16
|
+
type: {
|
|
17
|
+
type: "string",
|
|
18
|
+
enum: ["http", "mcp", "a2a", "all"],
|
|
19
|
+
description: "Filter by resource type (default all).",
|
|
20
|
+
},
|
|
21
|
+
network: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Filter by CAIP-2 network, e.g. eip155:190415.",
|
|
24
|
+
},
|
|
25
|
+
limit: { type: "number", description: "Max results (default 20, max 50)." },
|
|
26
|
+
},
|
|
27
|
+
additionalProperties: false,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
export const HPP_CALL_TOOL = {
|
|
31
|
+
name: "hpp_call",
|
|
32
|
+
description: "Call a service found via hpp_discover. Pass its `resourceId` and a `body` " +
|
|
33
|
+
"(the service's input args). Payment (USDC.e) is handled automatically with " +
|
|
34
|
+
"your wallet, subject to the daily spend cap — you do not sign anything. " +
|
|
35
|
+
"HTTP-typed services are called directly; MCP/A2A-typed services return " +
|
|
36
|
+
"connection guidance.",
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: "object",
|
|
39
|
+
properties: {
|
|
40
|
+
resourceId: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "Service id returned by hpp_discover.",
|
|
43
|
+
},
|
|
44
|
+
body: {
|
|
45
|
+
type: "object",
|
|
46
|
+
description: "Request body / input args for the service.",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
required: ["resourceId"],
|
|
50
|
+
additionalProperties: false,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
function errorResult(text) {
|
|
54
|
+
return { content: [{ type: "text", text }], isError: true };
|
|
55
|
+
}
|
|
56
|
+
export async function hppDiscover(client, args) {
|
|
57
|
+
const resources = await client.discover(args);
|
|
58
|
+
const services = resources.map((r) => ({
|
|
59
|
+
resourceId: r.id,
|
|
60
|
+
type: r.type,
|
|
61
|
+
description: r.description ?? r.toolName ?? r.resourceUrl,
|
|
62
|
+
priceAtomic: r.priceAtomic,
|
|
63
|
+
asset: r.asset,
|
|
64
|
+
network: r.network,
|
|
65
|
+
scheme: r.scheme,
|
|
66
|
+
...(r.toolName ? { toolName: r.toolName } : {}),
|
|
67
|
+
}));
|
|
68
|
+
return {
|
|
69
|
+
content: [
|
|
70
|
+
{ type: "text", text: JSON.stringify({ count: services.length, services }) },
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export async function hppCall(deps, client, args) {
|
|
75
|
+
if (!args.resourceId || typeof args.resourceId !== "string") {
|
|
76
|
+
return errorResult("resourceId required");
|
|
77
|
+
}
|
|
78
|
+
let detail;
|
|
79
|
+
try {
|
|
80
|
+
detail = await client.detail(args.resourceId);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
return errorResult(`discovery lookup failed: ${err.message}`);
|
|
84
|
+
}
|
|
85
|
+
if (detail.type !== "http") {
|
|
86
|
+
return errorResult(`resource "${args.resourceId}" is type "${detail.type}" — connect to it ` +
|
|
87
|
+
`directly at ${detail.resourceUrl}` +
|
|
88
|
+
(detail.type === "a2a"
|
|
89
|
+
? ` (use pay_a2a_agent with its skill id).`
|
|
90
|
+
: ` (MCP transport).`));
|
|
91
|
+
}
|
|
92
|
+
// Curated discovery is the trust boundary → skip the manual host allowlist
|
|
93
|
+
// (trustedSource) but keep the spend cap. Exact-scheme only today; upto/batch
|
|
94
|
+
// resources surface a clear "no exact accept" error (follow-up).
|
|
95
|
+
return x402HttpCall({ ...deps, trustedSource: true }, {
|
|
96
|
+
url: detail.resourceUrl,
|
|
97
|
+
method: detail.httpMethod ?? "POST",
|
|
98
|
+
body: args.body,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=discoveryTools.js.map
|