@hpp-io/x402-mcp-bridge 0.0.1 → 0.0.3
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 +125 -77
- package/bin/hpp-x402.js +5 -0
- package/bin/x402-mcp-bridge.js +0 -0
- package/dist/a2a.d.ts +70 -0
- package/dist/a2a.js +210 -0
- package/dist/a2a.js.map +1 -0
- package/dist/autoTopup.d.ts +2 -1
- package/dist/autoTopup.js.map +1 -1
- package/dist/cli/channel.d.ts +1 -0
- package/dist/cli/channel.js +323 -0
- package/dist/cli/channel.js.map +1 -0
- package/dist/cli/hpp-x402.d.ts +2 -0
- package/dist/cli/hpp-x402.js +375 -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-claude.d.ts +2 -20
- package/dist/cli/install-claude.js +12 -63
- package/dist/cli/install-claude.js.map +1 -1
- 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 +35 -0
- package/dist/cli/install-mcp-host.js +82 -0
- package/dist/cli/install-mcp-host.js.map +1 -0
- package/dist/cli/install-openclaw.d.ts +7 -0
- package/dist/cli/install-openclaw.js +28 -0
- package/dist/cli/install-openclaw.js.map +1 -0
- 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 -0
- package/dist/cli/policy.js +212 -0
- package/dist/cli/policy.js.map +1 -0
- 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 +4172 -9580
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +24 -6
- package/dist/cli/setup.js.map +1 -1
- package/dist/client.d.ts +25 -10
- package/dist/client.js +139 -2
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +50 -11
- package/dist/config.js +50 -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 +27 -0
- package/dist/funds/direct-balance.js +58 -0
- package/dist/funds/direct-balance.js.map +1 -0
- package/dist/funds.d.ts +26 -0
- package/dist/funds.js +2 -0
- package/dist/funds.js.map +1 -0
- package/dist/httpX402.d.ts +45 -0
- package/dist/httpX402.js +214 -0
- package/dist/httpX402.js.map +1 -0
- package/dist/index.js +66 -20
- package/dist/index.js.map +1 -1
- package/dist/keychain.d.ts +23 -0
- package/dist/keychain.js +111 -0
- package/dist/keychain.js.map +1 -0
- package/dist/policy.d.ts +73 -0
- package/dist/policy.js +249 -0
- package/dist/policy.js.map +1 -0
- package/dist/server.d.ts +18 -1
- package/dist/server.js +120 -10
- package/dist/server.js.map +1 -1
- package/docs/policy.md +101 -0
- package/package.json +11 -8
- package/bin/hpp-x402-safe-revoke.js +0 -5
- package/bin/hpp-x402-safe-setup.js +0 -5
package/dist/server.js
CHANGED
|
@@ -14,25 +14,135 @@
|
|
|
14
14
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
15
15
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
16
16
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
17
|
+
import { PAY_A2A_TOOL, payA2aAgent } from "./a2a.js";
|
|
18
|
+
import { X402_HTTP_TOOL, x402HttpCall } from "./httpX402.js";
|
|
19
|
+
import { HPP_DISCOVER_TOOL, HPP_CALL_TOOL, hppDiscover, hppCall, } from "./discoveryTools.js";
|
|
17
20
|
import { log } from "./log.js";
|
|
18
21
|
export async function startBridgeServer(opts) {
|
|
19
22
|
const server = new Server({ name: opts.name, version: opts.version }, { capabilities: { tools: {} } });
|
|
20
|
-
// ---- listTools —
|
|
23
|
+
// ---- listTools — upstream tools (if any) + local tools --------------
|
|
21
24
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
22
|
-
const upstreamTools = await opts.upstream.base.listTools();
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
const upstreamTools = opts.upstream ? await opts.upstream.base.listTools() : { tools: [] };
|
|
26
|
+
const localTools = opts.discovery
|
|
27
|
+
? [PAY_A2A_TOOL, X402_HTTP_TOOL, HPP_DISCOVER_TOOL, HPP_CALL_TOOL]
|
|
28
|
+
: [PAY_A2A_TOOL, X402_HTTP_TOOL];
|
|
29
|
+
log.debug("listTools", { count: upstreamTools.tools.length + localTools.length });
|
|
30
|
+
return { tools: [...upstreamTools.tools, ...localTools] };
|
|
25
31
|
});
|
|
26
32
|
// ---- callTool — forward through x402-aware wrapper ------------------
|
|
27
|
-
|
|
33
|
+
//
|
|
34
|
+
// Long-running tools: the upstream resource-server emits
|
|
35
|
+
// `notifications/progress` every ~25s while it inline-waits for an
|
|
36
|
+
// on-chain X402Delivered event. We forward each one to the host using
|
|
37
|
+
// the host's own progressToken (from extra._meta) so its idle timer
|
|
38
|
+
// resets and the request doesn't get cancelled at 60s. Without this,
|
|
39
|
+
// any compute taking longer than ~55s gets killed at the host's MCP
|
|
40
|
+
// client timeout, regardless of what the server eventually returns.
|
|
41
|
+
//
|
|
42
|
+
// `resetTimeoutOnProgress: true` on the upstream call applies the same
|
|
43
|
+
// protection on the bridge → resource-server hop. `timeout: 300_000`
|
|
44
|
+
// gives the upstream up to 5 minutes (well past anything we'd run
|
|
45
|
+
// inline) before bridge gives up.
|
|
46
|
+
server.setRequestHandler(CallToolRequestSchema, async (req, extra) => {
|
|
28
47
|
const { name, arguments: args } = req.params;
|
|
29
48
|
log.info("callTool.start", { name });
|
|
49
|
+
// Local tool: pay an external A2A agent (not an upstream MCP tool).
|
|
50
|
+
if (name === PAY_A2A_TOOL.name) {
|
|
51
|
+
try {
|
|
52
|
+
return await payA2aAgent({
|
|
53
|
+
signer: opts.signer,
|
|
54
|
+
network: opts.network,
|
|
55
|
+
funds: opts.funds,
|
|
56
|
+
rpcTimeoutMs: opts.a2aRpcTimeoutMs,
|
|
57
|
+
}, (args ?? {}));
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
61
|
+
log.error("pay_a2a_agent.failed", { err: msg });
|
|
62
|
+
return { content: [{ type: "text", text: `pay_a2a_agent error: ${msg}` }], isError: true };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Local tool: call an x402-protected HTTP endpoint (not an upstream MCP
|
|
66
|
+
// tool). Auth headers + spend limits come from local policy; payment is
|
|
67
|
+
// signed with the bridge's delegate wallet.
|
|
68
|
+
if (name === X402_HTTP_TOOL.name) {
|
|
69
|
+
try {
|
|
70
|
+
return await x402HttpCall({
|
|
71
|
+
signer: opts.signer,
|
|
72
|
+
network: opts.network,
|
|
73
|
+
funds: opts.funds,
|
|
74
|
+
}, (args ?? {}));
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
78
|
+
log.error("x402_http_call.failed", { err: msg });
|
|
79
|
+
return { content: [{ type: "text", text: `x402_http_call error: ${msg}` }], isError: true };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Local tool: discover curated x402 services (read-only, no payment).
|
|
83
|
+
if (opts.discovery && name === HPP_DISCOVER_TOOL.name) {
|
|
84
|
+
try {
|
|
85
|
+
return await hppDiscover(opts.discovery, (args ?? {}));
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
89
|
+
log.error("hpp_discover.failed", { err: msg });
|
|
90
|
+
return { content: [{ type: "text", text: `hpp_discover error: ${msg}` }], isError: true };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Local tool: call a discovered service by id (payment via our wallet).
|
|
94
|
+
if (opts.discovery && name === HPP_CALL_TOOL.name) {
|
|
95
|
+
try {
|
|
96
|
+
return await hppCall({ signer: opts.signer, network: opts.network, funds: opts.funds }, opts.discovery, (args ?? {}));
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
100
|
+
log.error("hpp_call.failed", { err: msg });
|
|
101
|
+
return { content: [{ type: "text", text: `hpp_call error: ${msg}` }], isError: true };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Beyond the local tools above, everything is an upstream resource-server
|
|
105
|
+
// tool. In local-tools-only mode there's no upstream to forward to.
|
|
106
|
+
if (!opts.upstream) {
|
|
107
|
+
return {
|
|
108
|
+
content: [{ type: "text", text: `unknown tool: ${name} (no upstream resource server configured)` }],
|
|
109
|
+
isError: true,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const up = opts.upstream;
|
|
113
|
+
const hostProgressToken = extra._meta?.progressToken;
|
|
30
114
|
try {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
115
|
+
// x402MCPClient's typed callTool options omit `onprogress`, but at
|
|
116
|
+
// runtime the underlying mcpClient.callTool receives the options
|
|
117
|
+
// object unchanged — so onprogress IS honoured by the SDK. Cast
|
|
118
|
+
// around the type gap; remove once @x402/mcp upstream broadens its
|
|
119
|
+
// option type.
|
|
120
|
+
const upstreamOptions = {
|
|
121
|
+
timeout: 300_000,
|
|
122
|
+
resetTimeoutOnProgress: true,
|
|
123
|
+
onprogress: hostProgressToken !== undefined
|
|
124
|
+
? (p) => {
|
|
125
|
+
extra
|
|
126
|
+
.sendNotification({
|
|
127
|
+
method: "notifications/progress",
|
|
128
|
+
params: {
|
|
129
|
+
progressToken: hostProgressToken,
|
|
130
|
+
progress: p.progress,
|
|
131
|
+
total: p.total,
|
|
132
|
+
message: p.message,
|
|
133
|
+
},
|
|
134
|
+
})
|
|
135
|
+
.catch((err) => {
|
|
136
|
+
log.debug("progress.forwardFailed", {
|
|
137
|
+
err: err.message,
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
: undefined,
|
|
142
|
+
};
|
|
143
|
+
const result = await up.x402.callTool(name, (args ?? {}), upstreamOptions);
|
|
144
|
+
const paymentMade = result.paymentMade ?? false;
|
|
145
|
+
log.info("callTool.done", { name, paymentMade });
|
|
36
146
|
// Strip bridge-internal fields (paymentMade, paymentResponse) before
|
|
37
147
|
// returning to host — they're not part of the MCP CallToolResult shape.
|
|
38
148
|
return {
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/docs/policy.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Host policy (`policy.json`) — 레퍼런스
|
|
2
|
+
|
|
3
|
+
`x402_http_call` 도구가 읽는 **host별 인증 헤더 주입 + 지출 가드레일** 설정. 서비스마다 다른 부분을
|
|
4
|
+
코드가 아닌 데이터로 두어, 새 서비스 추가가 한 줄이고 어떤 호스트도 하드코딩되지 않습니다.
|
|
5
|
+
|
|
6
|
+
## 위치
|
|
7
|
+
|
|
8
|
+
- 기본: `~/.hpp-x402/policy.json` (디렉토리는 `$HPP_X402_HOME`로 변경 가능)
|
|
9
|
+
- override: `$HPP_X402_CRED_FILE` (파일 경로 직접 지정)
|
|
10
|
+
- bridge가 **매 도구 호출마다 읽음** → 수정 후 재시작 불필요
|
|
11
|
+
- 정확 경로 확인: `hpp-x402-policy path`
|
|
12
|
+
|
|
13
|
+
## 스키마
|
|
14
|
+
|
|
15
|
+
```jsonc
|
|
16
|
+
{
|
|
17
|
+
"_defaults": {
|
|
18
|
+
"allowUnlisted": false, // 미등록 host 허용? (기본 false = 거부 = allowlist)
|
|
19
|
+
"limits": { "requireHttps": true, "maxPerCallAtomic": "1000000" }
|
|
20
|
+
},
|
|
21
|
+
"<host>": { // 정확 일치(포트 포함, 소문자). wildcard 없음
|
|
22
|
+
"headers": { "<HeaderName>": "<value-source>" },
|
|
23
|
+
"limits": {
|
|
24
|
+
"requireHttps": true, // https 강제 (로컬 http면 false)
|
|
25
|
+
"maxPerCallAtomic": "5000000", // 1회 상한 (atomic, USDC.e 6dec → 5000000 = 5)
|
|
26
|
+
"cooldownMs": 300000, // 결제 간 최소 간격(ms) — 멱등(H2)
|
|
27
|
+
"maxPerDayAtomic": "20000000" // (파싱만, 일일 ledger는 후속)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`host`는 `new URL(url).host`(소문자). 정책에 없고 `allowUnlisted=false`면 **결제 전 거부**.
|
|
34
|
+
|
|
35
|
+
## value-source (헤더 값 출처)
|
|
36
|
+
|
|
37
|
+
비밀을 파일에 직접 안 쓰고 참조로 둡니다. 호출 시 **로컬에서만** 해석 → 헤더로 주입(LLM/로그 미노출).
|
|
38
|
+
해석 실패 시 **무인증 전송 없이 에러로 중단**.
|
|
39
|
+
|
|
40
|
+
| 형식 | 의미 |
|
|
41
|
+
|------|------|
|
|
42
|
+
| `file:<path>#<field>` | JSON 파일 필드 (`~` 확장, 중첩 `a.b.c`) |
|
|
43
|
+
| `env:<VAR>` | 환경변수 |
|
|
44
|
+
| `keychain://<svc>/<acct>` | OS 키체인 |
|
|
45
|
+
| `literal:<value>` | 인라인 평문 (**dev 전용**) |
|
|
46
|
+
|
|
47
|
+
## 가드레일
|
|
48
|
+
|
|
49
|
+
| 키 | 효과 |
|
|
50
|
+
|----|------|
|
|
51
|
+
| `allowUnlisted` (_defaults) | false면 등록된 host만 호출 가능 (deny-by-default) |
|
|
52
|
+
| `requireHttps` | https 아닌 대상 거부 (로컬 http는 host별 false) |
|
|
53
|
+
| `maxPerCallAtomic` | 1회 결제 상한 — **서버가 준 402 금액**에 적용(악성 서버 방어) |
|
|
54
|
+
| `cooldownMs` | 직전 결제 후 이 시간 내 재결제는 직전 결과 반환(재결제 X) |
|
|
55
|
+
|
|
56
|
+
> 온체인 Safe AllowanceModule 일일 한도가 **최종 하드 상한**(정책 파일로 못 넘음).
|
|
57
|
+
|
|
58
|
+
## CLI — `hpp-x402-policy`
|
|
59
|
+
|
|
60
|
+
수동 JSON 편집 대신 사용 가능:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
hpp-x402-policy path # 파일 경로
|
|
64
|
+
hpp-x402-policy show # 전체 JSON
|
|
65
|
+
hpp-x402-policy list # host 요약
|
|
66
|
+
|
|
67
|
+
# host 추가/수정 (--header 반복 가능, --max-per-call은 USDC 단위 → atomic 자동 변환)
|
|
68
|
+
hpp-x402-policy set hub-stage.hpp.io \
|
|
69
|
+
--header X-Api-Key=file:~/.hpphub/config.json#api_key \
|
|
70
|
+
--max-per-call 5 --cooldown-ms 300000
|
|
71
|
+
|
|
72
|
+
hpp-x402-policy set localhost:4000 \
|
|
73
|
+
--header X-Api-Key=file:~/.hpphub/config.json#api_key \
|
|
74
|
+
--max-per-call 5 --https false # 로컬 http 허용
|
|
75
|
+
|
|
76
|
+
hpp-x402-policy unset <host> # host 삭제
|
|
77
|
+
hpp-x402-policy unset <host> --header NAME # 헤더 1개 삭제
|
|
78
|
+
|
|
79
|
+
hpp-x402-policy defaults --allow-unlisted false --max-per-call 1 --https true
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 예시 (완성형)
|
|
83
|
+
|
|
84
|
+
```jsonc
|
|
85
|
+
{
|
|
86
|
+
"_defaults": { "allowUnlisted": false, "limits": { "requireHttps": true, "maxPerCallAtomic": "1000000" } },
|
|
87
|
+
"hub-stage.hpp.io": {
|
|
88
|
+
"headers": { "X-Api-Key": "file:~/.hpphub/config.json#api_key" },
|
|
89
|
+
"limits": { "requireHttps": true, "maxPerCallAtomic": "5000000", "cooldownMs": 300000 }
|
|
90
|
+
},
|
|
91
|
+
"localhost:4000": {
|
|
92
|
+
"headers": { "X-Api-Key": "file:~/.hpphub/config.json#api_key" },
|
|
93
|
+
"limits": { "requireHttps": false, "maxPerCallAtomic": "5000000", "cooldownMs": 300000 }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 보안 메모
|
|
99
|
+
|
|
100
|
+
- 파일 퍼미션 0600 권장 (CLI는 0600으로 기록). `literal:` 평문은 dev 전용 — 운영은 `file:`/`keychain://`.
|
|
101
|
+
- value-source는 로컬에서만 해석, 결과는 **대상 host 요청 헤더로만** 전송. 로그/도구 args에 노출 안 됨.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hpp-io/x402-mcp-bridge",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "MCP stdio bridge that lets Claude Desktop / OpenClaw / other MCP hosts make x402 payments on HPP — autoTopup from a Safe via AllowanceModule, signs EIP-3009 with a delegate EOA.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"bin": {
|
|
10
10
|
"x402-mcp-bridge": "bin/x402-mcp-bridge.js",
|
|
11
|
-
"hpp-x402
|
|
12
|
-
"hpp-x402-safe-revoke": "bin/hpp-x402-safe-revoke.js"
|
|
11
|
+
"hpp-x402": "bin/hpp-x402.js"
|
|
13
12
|
},
|
|
14
13
|
"files": [
|
|
15
14
|
"dist",
|
|
16
15
|
"bin",
|
|
16
|
+
"docs/policy.md",
|
|
17
17
|
"README.md",
|
|
18
18
|
"LICENSE"
|
|
19
19
|
],
|
|
@@ -24,22 +24,25 @@
|
|
|
24
24
|
"build": "tsc",
|
|
25
25
|
"dev": "tsx src/index.ts",
|
|
26
26
|
"typecheck": "tsc --noEmit",
|
|
27
|
+
"postinstall": "patch-package || true",
|
|
27
28
|
"prepublishOnly": "npm run typecheck && npm run build"
|
|
28
29
|
},
|
|
29
30
|
"publishConfig": {
|
|
30
|
-
"access": "public"
|
|
31
|
-
"provenance": true
|
|
31
|
+
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
35
|
-
"@
|
|
36
|
-
"@x402/
|
|
37
|
-
"@x402/
|
|
35
|
+
"@napi-rs/keyring": "^1.3.0",
|
|
36
|
+
"@x402/core": "^2.14.0",
|
|
37
|
+
"@x402/evm": "^2.14.0",
|
|
38
|
+
"@x402/mcp": "^2.14.0",
|
|
39
|
+
"commander": "^12.1.0",
|
|
38
40
|
"viem": "^2.21.54",
|
|
39
41
|
"zod": "^3.23.8"
|
|
40
42
|
},
|
|
41
43
|
"devDependencies": {
|
|
42
44
|
"@types/node": "^20.0.0",
|
|
45
|
+
"patch-package": "^8.0.1",
|
|
43
46
|
"tsx": "^4.0.0",
|
|
44
47
|
"typescript": "^5.4.0"
|
|
45
48
|
}
|