@kaditang/402sentinel-mcp 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 +64 -0
- package/dist/index.js +105 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# 402sentinel-mcp
|
|
2
|
+
|
|
3
|
+
An MCP tool that lets your AI agent **check an x402 counterparty's risk before it
|
|
4
|
+
pays**. One tool, `assess_counterparty`: give it a payTo address, get back a
|
|
5
|
+
0–100 risk score + an `allow` / `review` / `block` decision, scored from on-chain
|
|
6
|
+
settlement behaviour on Base (address age, facilitator-aware payer diversity,
|
|
7
|
+
settlement maturity) with honest confidence/coverage.
|
|
8
|
+
|
|
9
|
+
It's a thin client for the hosted service at **https://402sentinel.com** — the
|
|
10
|
+
scoring model and facilitator-identification logic live server-side (closed); this
|
|
11
|
+
package only forwards the request and pays for it, so it's open source.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm i -g @kaditang/402sentinel-mcp
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Configure
|
|
20
|
+
|
|
21
|
+
Add to your MCP client (Claude Desktop, Cursor, etc.):
|
|
22
|
+
|
|
23
|
+
```jsonc
|
|
24
|
+
{
|
|
25
|
+
"mcpServers": {
|
|
26
|
+
"402sentinel": {
|
|
27
|
+
"command": "402sentinel-mcp",
|
|
28
|
+
"env": {
|
|
29
|
+
"CLIENT_PRIVATE_KEY": "0x... // a Base wallet with USDC in its Circle Gateway balance"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Each assessment costs **$0.01**, paid automatically in USDC via x402 (Circle
|
|
37
|
+
Gateway, gas-free on Base) from the configured wallet.
|
|
38
|
+
|
|
39
|
+
## Use
|
|
40
|
+
|
|
41
|
+
The agent calls it before authorizing a payment:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
assess_counterparty({
|
|
45
|
+
target: { payto_address: "0x..." },
|
|
46
|
+
payment_context: { amount: 10, asset: "USDC" },
|
|
47
|
+
policy: { block_at_score: 70, review_at_score: 40 }
|
|
48
|
+
})
|
|
49
|
+
→ { decision: "review", risk_score: 52, confidence: 0.41, coverage: {...}, dimensions: [...], recommendation: "..." }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- `block` → don't pay
|
|
53
|
+
- `review` → cap exposure / escrow
|
|
54
|
+
- `allow` → proceed
|
|
55
|
+
|
|
56
|
+
## Disclaimer
|
|
57
|
+
|
|
58
|
+
Algorithmic risk signal, informational only — **not advice, not an endorsement,
|
|
59
|
+
and not an accusation** about any party. Scores are probabilistic estimates from
|
|
60
|
+
limited public on-chain data and heuristics, and may misclassify. Do your own due
|
|
61
|
+
diligence; don't rely on it as your sole basis to pay or refuse. See
|
|
62
|
+
https://402sentinel.com/terms.
|
|
63
|
+
|
|
64
|
+
MIT.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 402Sentinel MCP — thin, open-source client.
|
|
4
|
+
*
|
|
5
|
+
* Exposes one tool, `assess_counterparty`, that an agent calls BEFORE paying an
|
|
6
|
+
* x402 counterparty. It pays $0.01 (x402, Circle Gateway on Base) to the hosted
|
|
7
|
+
* 402sentinel.com scoring service and returns a 0-100 risk score + allow/review/
|
|
8
|
+
* block decision. The scoring model / facilitator logic live server-side
|
|
9
|
+
* (closed); this client only forwards + pays, so it's safe to open-source.
|
|
10
|
+
*
|
|
11
|
+
* Config (env):
|
|
12
|
+
* CLIENT_PRIVATE_KEY — a Base wallet with USDC in its Circle Gateway balance
|
|
13
|
+
* (it pays $0.01 per assessment). Required.
|
|
14
|
+
* SENTINEL_URL — override base URL (default https://402sentinel.com).
|
|
15
|
+
*/
|
|
16
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
17
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
18
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
19
|
+
import { GatewayClient } from "@circle-fin/x402-batching/client";
|
|
20
|
+
const BASE = (process.env.SENTINEL_URL ?? "https://402sentinel.com").replace(/\/$/, "");
|
|
21
|
+
const RAW_PK = process.env.CLIENT_PRIVATE_KEY ?? "";
|
|
22
|
+
const TOOLS = [
|
|
23
|
+
{
|
|
24
|
+
name: "assess_counterparty",
|
|
25
|
+
description: "Assess the risk of an x402 counterparty (a payTo address) BEFORE paying. Returns a 0-100 risk_score and an allow/review/block decision relative to your policy, scored from on-chain settlement behaviour on Base (address age, facilitator-aware payer diversity, settlement maturity) with honest confidence/coverage. Call this before authorizing any x402 payment above your risk threshold. Costs $0.01 (paid automatically in USDC).",
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: "object",
|
|
28
|
+
required: ["target"],
|
|
29
|
+
properties: {
|
|
30
|
+
target: {
|
|
31
|
+
type: "object",
|
|
32
|
+
required: ["payto_address"],
|
|
33
|
+
properties: {
|
|
34
|
+
payto_address: { type: "string", description: "Chain address that will receive the payment" },
|
|
35
|
+
resource_url: { type: "string", description: "The x402 resource/endpoint URL (optional)" },
|
|
36
|
+
network: { type: "string", description: "CAIP-2 chain id, e.g. eip155:8453 (optional)" },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
payment_context: {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
amount: { type: "number", description: "Payment amount you're about to make" },
|
|
43
|
+
asset: { type: "string", description: "e.g. USDC" },
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
policy: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
block_at_score: { type: "number", description: "risk >= this => block (default 70)" },
|
|
50
|
+
review_at_score: { type: "number", description: "risk >= this => review (default 40)" },
|
|
51
|
+
min_confidence: { type: "number", description: "below this => force review (default 0.5)" },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
depth: { type: "string", enum: ["shallow", "deep"], description: "shallow=cheap/cached, deep=fresh (default shallow)" },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
function clientOrNull() {
|
|
60
|
+
if (!RAW_PK || RAW_PK.startsWith("0xYour"))
|
|
61
|
+
return null;
|
|
62
|
+
const pk = (RAW_PK.startsWith("0x") ? RAW_PK : `0x${RAW_PK}`);
|
|
63
|
+
return new GatewayClient({ chain: "base", privateKey: pk });
|
|
64
|
+
}
|
|
65
|
+
async function main() {
|
|
66
|
+
const server = new Server({ name: "402sentinel", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
67
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
68
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
69
|
+
const { name, arguments: args } = req.params;
|
|
70
|
+
if (name !== "assess_counterparty") {
|
|
71
|
+
return { content: [{ type: "text", text: `unknown tool: ${name}` }], isError: true };
|
|
72
|
+
}
|
|
73
|
+
const client = clientOrNull();
|
|
74
|
+
if (!client) {
|
|
75
|
+
return {
|
|
76
|
+
content: [{
|
|
77
|
+
type: "text",
|
|
78
|
+
text: JSON.stringify({
|
|
79
|
+
error: "CLIENT_PRIVATE_KEY not set. Provide a Base wallet (with USDC in its Circle Gateway balance) so this tool can pay $0.01 per assessment.",
|
|
80
|
+
}),
|
|
81
|
+
}],
|
|
82
|
+
isError: true,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
const { data } = await client.pay(`${BASE}/api/assess`, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
body: args,
|
|
89
|
+
});
|
|
90
|
+
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: "text", text: JSON.stringify({ error: `assessment failed: ${e.message}` }) }],
|
|
95
|
+
isError: true,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const transport = new StdioServerTransport();
|
|
100
|
+
await server.connect(transport);
|
|
101
|
+
}
|
|
102
|
+
main().catch((e) => {
|
|
103
|
+
console.error("402sentinel-mcp fatal:", e);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kaditang/402sentinel-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP tool to assess an x402 counterparty's risk BEFORE paying — allow/review/block, scored on-chain. Thin client for 402sentinel.com.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": { "402sentinel-mcp": "./dist/index.js" },
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"files": ["dist", "README.md"],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "node node_modules/typescript/bin/tsc",
|
|
11
|
+
"start": "node dist/index.js",
|
|
12
|
+
"dev": "node node_modules/tsx/dist/cli.mjs src/index.ts",
|
|
13
|
+
"prepublishOnly": "node node_modules/typescript/bin/tsc"
|
|
14
|
+
},
|
|
15
|
+
"keywords": ["x402", "mcp", "ai-agents", "risk", "counterparty", "base", "usdc"],
|
|
16
|
+
"author": "Biao Tang",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
20
|
+
"@circle-fin/x402-batching": "^3.0.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"tsx": "^4.0.0",
|
|
24
|
+
"typescript": "^5.0.0"
|
|
25
|
+
},
|
|
26
|
+
"mcpName": "io.github.kaditang/402sentinel-mcp"
|
|
27
|
+
}
|