warden402-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 +36 -0
- package/package.json +22 -0
- package/src/index.mjs +84 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# warden402-mcp
|
|
2
|
+
|
|
3
|
+
Warden'ın pre-execution güvenlik kontrollerini **MCP araçları** olarak sunan bir stdio
|
|
4
|
+
sunucusu. Ajan, herhangi bir on-chain aksiyondan önce çağırır; `block` dönerse yapmaz.
|
|
5
|
+
|
|
6
|
+
## Araçlar
|
|
7
|
+
|
|
8
|
+
| Araç | Ne zaman |
|
|
9
|
+
|------|----------|
|
|
10
|
+
| `guard_token` | Bir token'ı AL-SAT'tan önce (honeypot, vergi, likidite, holder, OFAC) |
|
|
11
|
+
| `guard_tx` | Bekleyen bir işlemi İMZALAMADAN önce (sınırsız approve, sanctioned counterparty) |
|
|
12
|
+
| `guard_address` | Bir karşı tarafla etkileşim öncesi (OFAC, kontrat riski, yaş) |
|
|
13
|
+
|
|
14
|
+
## MCP istemci yapılandırması
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"mcpServers": {
|
|
19
|
+
"warden402": {
|
|
20
|
+
"command": "npx",
|
|
21
|
+
"args": ["-y", "warden402-mcp"],
|
|
22
|
+
"env": { "WARDEN_API_URL": "https://warden402.xyz/api" }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`WARDEN_API_URL` opsiyoneldir (varsayılan `https://warden402.xyz/api`). Lokal geliştirme
|
|
29
|
+
için Hono API'yi doğrudan da gösterebilirsin (ör. `http://localhost:8787`, ama bu durumda
|
|
30
|
+
yol `/guard/token` olur — varsayılan Next proxy `/api/guard` bekler).
|
|
31
|
+
|
|
32
|
+
## Çalıştırma
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cd mcp && npm install && WARDEN_API_URL=https://warden402.xyz/api node src/index.mjs
|
|
36
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "warden402-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"mcpName": "io.github.sukrutkrdg/warden402-mcp",
|
|
5
|
+
"description": "MCP server exposing Warden's pre-execution safety checks (token / tx / address → block·review·clear) as agent tools for Base.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"bin": {
|
|
9
|
+
"warden402-mcp": "./src/index.mjs"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "node src/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"files": ["src", "README.md"],
|
|
15
|
+
"homepage": "https://warden402.xyz",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
18
|
+
"zod": "^3.23.0"
|
|
19
|
+
},
|
|
20
|
+
"engines": { "node": ">=20" },
|
|
21
|
+
"keywords": ["mcp", "x402", "base", "security", "agent", "warden"]
|
|
22
|
+
}
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* warden402-mcp
|
|
4
|
+
*
|
|
5
|
+
* Bir MCP stdio sunucusu. Warden'ın pre-execution güvenlik kontrollerini ajan
|
|
6
|
+
* araçları olarak sunar: bir token / bekleyen işlem / adres ver → block·review·clear.
|
|
7
|
+
*
|
|
8
|
+
* Ajan, herhangi bir on-chain aksiyondan (al-sat, imzala, approve) ÖNCE bu aracı
|
|
9
|
+
* çağırmalı ve 'block' dönerse işlemi yapmamalı.
|
|
10
|
+
*
|
|
11
|
+
* Opsiyonel env:
|
|
12
|
+
* WARDEN_API_URL – Warden API kökü (varsayılan: https://warden402.xyz/api)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
16
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
|
|
19
|
+
const API = (process.env.WARDEN_API_URL ?? "https://warden402.xyz/api").replace(/\/$/, "");
|
|
20
|
+
const log = (m) => process.stderr.write(`[warden402-mcp] ${m}\n`);
|
|
21
|
+
|
|
22
|
+
async function callGuard(path, init) {
|
|
23
|
+
const res = await fetch(`${API}${path}`, init);
|
|
24
|
+
const data = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
25
|
+
return data;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function asText(verdict) {
|
|
29
|
+
// Ajanın anlaması için kısa, kararı öne çıkaran özet + tam JSON.
|
|
30
|
+
const head =
|
|
31
|
+
verdict?.decision
|
|
32
|
+
? `DECISION=${String(verdict.decision).toUpperCase()} risk=${verdict.riskScore}/100` +
|
|
33
|
+
(verdict.degraded ? " (degraded)" : "") +
|
|
34
|
+
(verdict.reasons?.length ? ` reasons=${verdict.reasons.join(",")}` : "")
|
|
35
|
+
: "verdict alınamadı";
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{ type: "text", text: head },
|
|
39
|
+
{ type: "text", text: JSON.stringify(verdict, null, 2) },
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const server = new McpServer({ name: "warden402", version: "0.1.0" });
|
|
45
|
+
|
|
46
|
+
server.tool(
|
|
47
|
+
"guard_token",
|
|
48
|
+
"Bir Base token kontratını AL-SAT'tan önce güvenlik açısından değerlendir. Honeypot, sınırsız satış vergisi, likidite, holder yoğunluğu ve OFAC yaptırımını birleştirip block/review/clear döner. 'block' ise tokenı alma.",
|
|
49
|
+
{ address: z.string().describe("Token kontrat adresi (0x..40 hex)"), chainId: z.coerce.number().optional().describe("Zincir id (varsayılan 8453 Base)") },
|
|
50
|
+
async ({ address, chainId }) => {
|
|
51
|
+
const q = new URLSearchParams({ type: "token", address, ...(chainId ? { chainId: String(chainId) } : {}) });
|
|
52
|
+
return asText(await callGuard(`/guard?${q.toString()}`));
|
|
53
|
+
},
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
server.tool(
|
|
57
|
+
"guard_tx",
|
|
58
|
+
"Bekleyen bir işlemi İMZALAMADAN önce değerlendir. Calldata'yı çözer (sınırsız approve / setApprovalForAll), karşı tarafı OFAC ve kontrat riskine karşı kontrol eder. 'block'/'review' ise imzalama.",
|
|
59
|
+
{
|
|
60
|
+
from: z.string().describe("Gönderen adres"),
|
|
61
|
+
to: z.string().describe("Hedef kontrat/adres"),
|
|
62
|
+
calldata: z.string().describe("İşlem calldata'sı (0x..)"),
|
|
63
|
+
value: z.string().optional().describe("Wei cinsinden value (opsiyonel)"),
|
|
64
|
+
chainId: z.coerce.number().optional(),
|
|
65
|
+
},
|
|
66
|
+
async ({ from, to, calldata, value, chainId }) => {
|
|
67
|
+
const body = { type: "tx", from, to, calldata, ...(value ? { value } : {}), ...(chainId ? { chainId } : {}) };
|
|
68
|
+
return asText(await callGuard(`/guard`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) }));
|
|
69
|
+
},
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
server.tool(
|
|
73
|
+
"guard_address",
|
|
74
|
+
"Bir karşı taraf adresini (counterparty) etkileşimden önce değerlendir: OFAC yaptırımı, kontrat riski ve yaş/aktivite. block/review/clear döner.",
|
|
75
|
+
{ address: z.string().describe("Değerlendirilecek adres (0x..40 hex)"), chainId: z.coerce.number().optional() },
|
|
76
|
+
async ({ address, chainId }) => {
|
|
77
|
+
const q = new URLSearchParams({ type: "address", address, ...(chainId ? { chainId: String(chainId) } : {}) });
|
|
78
|
+
return asText(await callGuard(`/guard?${q.toString()}`));
|
|
79
|
+
},
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const transport = new StdioServerTransport();
|
|
83
|
+
await server.connect(transport);
|
|
84
|
+
log(`hazır → ${API}`);
|