twzrd-mcp-server 0.1.0 → 0.2.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 ADDED
@@ -0,0 +1,114 @@
1
+ # twzrd-mcp-server - auto-pay MCP for the TWZRD Trust API
2
+
3
+ > Payment mechanism is mainnet-verified via the official x402 SDK (Python path,
4
+ > $0.001 moved 2026-06-26 - see Status). As of v0.2.0 the bundled TypeScript path
5
+ > uses the official x402 JS SDK (`@x402/core` + `@x402/svm` + `@x402/fetch`) and
6
+ > is construct-verified against the live mainnet challenge; one real on-chain
7
+ > settle remains before npm publish.
8
+
9
+ Auto-pay MCP server for TWZRD's Trust API, matching the competitor GTM shape
10
+ (anchor-x402, Br0ski777, BitBooth all ship one). An agent adds one `mcpServers`
11
+ entry; paid tool calls auto-handle the x402 challenge. Free tools never pay.
12
+
13
+ ## Why this is a corrected rebuild
14
+ A first draft signed **EIP-3009 on Base (EVM/viem)**. TWZRD settles x402 on
15
+ **Solana** (`scheme:"exact"`, USDC, sponsored `feePayer`) — the EVM scheme never
16
+ matches the challenge, so that draft could not pay TWZRD at all (it would `tsc`-pass
17
+ yet fail every real call). This version is Solana-native and **refuses** any
18
+ non-Solana challenge instead of mis-signing.
19
+
20
+ ## Safety guardrails (enforced before any signature)
21
+ - Per-call cap `TWZRD_MAX_USDC_PER_CALL` (default 0.05)
22
+ - Cumulative session cap `TWZRD_MAX_USDC_TOTAL` (default 1.00)
23
+ - Free discovery tools never enter the payment path
24
+ - No cross-chain fallback — a non-`exact`/non-`solana:` challenge is rejected
25
+ - Paid calls run the free preflight first; `decision=block` aborts the pay
26
+
27
+ ## Status — payment path VERIFIED on mainnet 2026-06-26
28
+
29
+ Two authorized settles from dev wallet `2pHjZLqs…`:
30
+
31
+ 1. **Hand-rolled `X-Payment` (this MCP's original approach): FAILED** — HTTP 402,
32
+ no USDC moved. The intel host validates via the official x402 lib's
33
+ `PaymentPayload`, so a hand-built header is rejected. (Green `tsc` ≠ settles —
34
+ fail-closed default was correct.)
35
+ 2. **Official x402 SDK: SUCCEEDED** — `GET /v1/intel/quick/CqtQPaAuQ5UR…` →
36
+ **HTTP 200, `"paid":true,"charged_amount_usdc":0.001`**, tier Silver score 53.6.
37
+ USDC balance moved `0.057236 → 0.056236` (exactly $0.001). A second call against
38
+ a no-data pubkey returned `422 charged:false` — the server's no-charge-on-empty
39
+ guard works.
40
+
41
+ **Conclusion: auto-pay works ONLY via the official x402 SDK, not a hand-rolled
42
+ header.** Proven client wiring (Python):
43
+
44
+ ```python
45
+ from x402.client import x402ClientSync
46
+ from x402.mechanisms.svm.signers import KeypairSigner
47
+ from x402.mechanisms.svm.exact import register_exact_svm_client
48
+ from x402.http.clients.requests import x402_requests
49
+ client = x402ClientSync()
50
+ register_exact_svm_client(client, KeypairSigner(keypair), rpc_url=RPC)
51
+ session = x402_requests(client)
52
+ session.get("https://intel.twzrd.xyz/v1/intel/quick/<wallet>") # auto-pays $0.001
53
+ ```
54
+
55
+ ### TypeScript path — integrated (v0.2.0)
56
+ The hand-rolled `payAndRetry` is replaced with the official x402 JS SDK
57
+ (`@x402/core` client + `@x402/svm` ExactSvmScheme + `@x402/fetch`
58
+ `wrapFetchWithPayment`). `@x402/svm` reads the challenge `extra.feePayer` and builds
59
+ the partially-signed sponsored transfer (verified no-spend against the live mainnet
60
+ challenge: 496-byte tx, 2 signature slots), and the SDK encodes the `X-PAYMENT`
61
+ header the server validates. Spend caps + preflight gate + free/paid split are
62
+ preserved — caps are enforced in the payment selector before any signature.
63
+ **Remaining:** one real $0.001 on-chain settle to confirm end-to-end, then npm
64
+ publish + MCP-registry listing.
65
+
66
+ ## Install & Config
67
+
68
+ ### Python (recommended — the mainnet-proven path)
69
+ ```bash
70
+ pip install twzrd-mcp
71
+ ```
72
+ MCP client config (`mcpServers`):
73
+ ```json
74
+ { "mcpServers": { "twzrd": {
75
+ "command": "twzrd-mcp",
76
+ "env": {
77
+ "TWZRD_RPC_URL": "<your Solana RPC url>",
78
+ "TWZRD_WALLET_KEYPAIR": "/path/to/solana-keypair.json",
79
+ "TWZRD_MCP_PAYMENTS_ENABLED": "1",
80
+ "TWZRD_MAX_USDC_PER_CALL": "0.05",
81
+ "TWZRD_MAX_USDC_TOTAL": "1.00"
82
+ }
83
+ }}}
84
+ ```
85
+ The **free** tools (`preflight`, `wallet_lookup`) need no wallet and no flags — leave
86
+ `TWZRD_MCP_PAYMENTS_ENABLED` unset and they work read-only. Only the paid tools need
87
+ the keypair + `TWZRD_MCP_PAYMENTS_ENABLED=1`.
88
+
89
+ ### Node (`npx twzrd-mcp-server`) — v0.2.0, x402 JS SDK
90
+ ```json
91
+ { "mcpServers": { "twzrd": {
92
+ "command": "npx", "args": ["-y", "twzrd-mcp-server"],
93
+ "env": {
94
+ "TWZRD_WALLET_SECRET_KEY": "<base58 Solana secret>",
95
+ "TWZRD_RPC_URL": "<your Solana RPC url>",
96
+ "TWZRD_MAX_USDC_PER_CALL": "0.05",
97
+ "TWZRD_MAX_USDC_TOTAL": "1.00"
98
+ }
99
+ }}}
100
+ ```
101
+ Auto-pay is enabled whenever `TWZRD_WALLET_SECRET_KEY` is present (set
102
+ `TWZRD_MCP_PAYMENTS_ENABLED=0` to force paid tools off). Free tools need no wallet.
103
+ Construct-verified against the live mainnet challenge; pending one real settle +
104
+ npm publish (until published, `npx twzrd-mcp-server` is not yet resolvable — see
105
+ the Python package above for a path that is live on PyPI today).
106
+
107
+ ## Tools
108
+ - `preflight` (free) — allow/warn/block + trust_score before you pay a **seller** you're about to transact with
109
+ - `wallet_lookup` (free) — facilitators + counterparty breadth for a Solana wallet
110
+ - `verify_receipt` (free) — independently verify a wallet's cNFT Receipt offline (Ed25519 vs the genesis authority `2ELSDx`); no trust in any TWZRD server
111
+ - `quick_trust` ($0.001, auto-pay) — quick tier + score for any wallet
112
+ - `full_trust` ($0.05, auto-pay) — full trust intel + signed V6 receipt
113
+
114
+ > Note: `quick_trust`/`full_trust` pay TWZRD a fixed micro-fee for intel on **any** wallet — they do **not** refuse "risky" targets (you look those up on purpose). Use `preflight` to vet a counterparty you're about to *pay elsewhere*.
package/dist/index.js CHANGED
@@ -1,257 +1,153 @@
1
1
  /**
2
- * TWZRD MCP Server — auto-pay x402 wrapper for TWZRD's Trust API.
2
+ * TWZRD MCP Server — auto-pay x402 wrapper for TWZRD's Trust API (SOLANA).
3
3
  *
4
- * Solana x402: the 402 challenge includes a sponsored feePayer + recentBlockhash.
5
- * The MCP builds a USDC transfer, signs with the agent's Solana keypair, retries.
6
- * Always runs free preflight before auto-paying (spend cap enforced).
4
+ * Agents install this MCP server; paid tool calls auto-handle the x402 challenge
5
+ * (detect 402 -> SDK builds + signs a Solana USDC payment -> retry). Free tools
6
+ * never pay.
7
+ *
8
+ * PAYMENT CORE: the official x402 SDK (@x402/core + @x402/svm + @x402/fetch).
9
+ * TWZRD settles x402 on **Solana** ("exact" scheme, USDC, sponsored feePayer):
10
+ * the buyer partial-signs a USDC transfer as the transfer authority, and TWZRD's
11
+ * wallet (the challenge `extra.feePayer`) co-signs + pays the SOL fee server-side.
12
+ * `@x402/svm`'s ExactSvmScheme reads `extra.feePayer` and builds exactly this
13
+ * partially-signed transaction; the SDK also encodes the X-PAYMENT header the
14
+ * server validates. (An earlier draft hand-rolled both and the server rejected
15
+ * it — the hand-rolled header never matched the official x402 PaymentPayload.)
16
+ *
17
+ * SAFETY GUARDRAILS (all enforced in the payment-requirements selector, BEFORE
18
+ * any signature):
19
+ * - Hard per-call cap (TWZRD_MAX_USDC_PER_CALL, default 0.05)
20
+ * - Cumulative session cap (TWZRD_MAX_USDC_TOTAL, default 1.00)
21
+ * - Free discovery tools are NEVER routed through the payment path
22
+ * - No cross-chain fallback: only a Solana "exact" requirement is selectable;
23
+ * anything else throws (refuse to pay) rather than mis-signing
24
+ * - Paid tools run the FREE preflight first; decision=block aborts the pay
25
+ *
26
+ * STATUS: payment mechanism is SDK-backed and the payload construction is
27
+ * verified against the live Solana "exact" challenge. The first real on-chain
28
+ * settle is the operator's go (needs a funded wallet). Set
29
+ * TWZRD_MCP_PAYMENTS_ENABLED=0 to force paid tools off (fail-closed) if desired.
7
30
  *
8
31
  * ENV:
9
- * TWZRD_SOLANA_KEYPAIR Solana keypair JSON array (from solana config)
10
- * TWZRD_API_URL — Base URL (default: https://intel.twzrd.xyz)
11
- * TWZRD_SPEND_CAP_USDC — Max USDC per call (default: 0.05)
12
- * TWZRD_DAILY_CAP_USDC — Max USDC per day (default: 1.00)
32
+ * TWZRD_WALLET_SECRET_KEY base58 Solana secret key (64-byte). Required for paid calls.
33
+ * TWZRD_RPC_URL Solana RPC (default mainnet-beta public)
34
+ * TWZRD_API_URL default https://intel.twzrd.xyz
35
+ * TWZRD_MAX_USDC_PER_CALL default 0.05
36
+ * TWZRD_MAX_USDC_TOTAL default 1.00
37
+ * TWZRD_MCP_PAYMENTS_ENABLED "0" to force paid tools off (default: enabled when a key is present)
13
38
  */
14
39
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
15
40
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
16
- import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
17
- import { Connection, Keypair, PublicKey, TransactionMessage, VersionedTransaction, } from "@solana/web3.js";
18
- import { getOrCreateAssociatedTokenAccount, createTransferInstruction } from "@solana/spl-token";
19
- import * as fs from "fs";
20
- import * as path from "path";
41
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
42
+ import { x402Client } from "@x402/core/client";
43
+ import { wrapFetchWithPayment } from "@x402/fetch";
44
+ import { ExactSvmScheme, SOLANA_MAINNET_CAIP2 } from "@x402/svm";
45
+ import { createKeyPairSignerFromBytes } from "@solana/kit";
46
+ import bs58 from "bs58";
21
47
  // ── Config ─────────────────────────────────────────────────────────────────
22
48
  const API_BASE = process.env.TWZRD_API_URL || "https://intel.twzrd.xyz";
23
- const KEYPAIR_SOURCE = process.env.TWZRD_SOLANA_KEYPAIR || "";
24
- const SPEND_CAP_USDC = parseFloat(process.env.TWZRD_SPEND_CAP_USDC || "0.05");
25
- const DAILY_CAP_USDC = parseFloat(process.env.TWZRD_DAILY_CAP_USDC || "1.00");
26
- if (!KEYPAIR_SOURCE) {
27
- console.error("TWZRD_SOLANA_KEYPAIR required set to the Solana keypair JSON path or array");
28
- process.exit(1);
29
- }
30
- // ── Solana wallet ──────────────────────────────────────────────────────────
31
- function loadKeypair(source) {
32
- let bytes;
33
- if (source.startsWith("[") || source.startsWith("{")) {
34
- const parsed = JSON.parse(source);
35
- const arr = Array.isArray(parsed) ? parsed : (parsed.secretKey || parsed);
36
- bytes = Uint8Array.from(arr);
49
+ const RPC_URL = process.env.TWZRD_RPC_URL || "https://api.mainnet-beta.solana.com";
50
+ const MAX_PER_CALL = Number(process.env.TWZRD_MAX_USDC_PER_CALL || "0.05");
51
+ const MAX_TOTAL = Number(process.env.TWZRD_MAX_USDC_TOTAL || "1.00");
52
+ const PAYMENTS_DISABLED = process.env.TWZRD_MCP_PAYMENTS_ENABLED === "0";
53
+ const SECRET = process.env.TWZRD_WALLET_SECRET_KEY || "";
54
+ let spentUsdc = 0; // cumulative session spend (USDC)
55
+ // ── Payment client (official x402 SDK, Solana exact scheme) ──────────────────
56
+ // The selector is the single chokepoint for every guardrail: it picks which
57
+ // `accepts[]` entry to pay and THROWS to refuse. Nothing is signed unless a
58
+ // requirement passes scheme + chain + per-call + session checks here first.
59
+ function selectSolanaExact(_x402Version, accepts) {
60
+ const req = (accepts || []).find((a) => a?.scheme === "exact" && String(a?.network || "").startsWith("solana:"));
61
+ if (!req) {
62
+ throw new Error(`Refusing to pay: no Solana "exact" payment option in challenge (${JSON.stringify((accepts || []).map((a) => ({ scheme: a?.scheme, network: a?.network })))})`);
37
63
  }
38
- else {
39
- // Path to keypair file
40
- const content = fs.readFileSync(path.resolve(source), "utf-8");
41
- bytes = Uint8Array.from(JSON.parse(content));
64
+ const decimals = Number(req.extra?.decimals ?? 6);
65
+ const amountUsdc = Number(BigInt(req.amount)) / 10 ** decimals;
66
+ if (amountUsdc > MAX_PER_CALL) {
67
+ throw new Error(`Refusing: call price $${amountUsdc} exceeds per-call cap $${MAX_PER_CALL}`);
42
68
  }
43
- return Keypair.fromSecretKey(bytes);
44
- }
45
- const agentKeypair = loadKeypair(KEYPAIR_SOURCE);
46
- const agentPubkey = agentKeypair.publicKey.toBase58();
47
- // ── Spend cap tracking (in-memory, per-process) ────────────────────────────
48
- let dailySpentUsdc = 0;
49
- let dailyResetAt = Date.now() + 24 * 60 * 60 * 1000;
50
- function checkSpendCap(amountUsdc) {
51
- const now = Date.now();
52
- if (now > dailyResetAt) {
53
- dailySpentUsdc = 0;
54
- dailyResetAt = now + 24 * 60 * 60 * 1000;
69
+ if (spentUsdc + amountUsdc > MAX_TOTAL) {
70
+ throw new Error(`Refusing: would exceed session cap $${MAX_TOTAL} (spent $${spentUsdc})`);
55
71
  }
56
- if (amountUsdc > SPEND_CAP_USDC)
57
- throw new Error(`Per-call spend cap ${SPEND_CAP_USDC} USDC exceeded (requested: ${amountUsdc})`);
58
- if (dailySpentUsdc + amountUsdc > DAILY_CAP_USDC)
59
- throw new Error(`Daily spend cap ${DAILY_CAP_USDC} USDC exceeded (spent: ${dailySpentUsdc}, would add: ${amountUsdc})`);
72
+ // Conservative accounting: count the spend at selection time. A failed settle
73
+ // only makes the caps stricter (never looser), which is the safe direction.
74
+ spentUsdc += amountUsdc;
75
+ return req;
60
76
  }
61
- // ── x402 fetch: 402 preflight sign retry (Solana scheme="exact") ─────
62
- async function twzrdFetch(path, options) {
63
- const url = `${API_BASE}${path}`;
64
- const method = options?.method || "GET";
65
- const body = options?.body ? JSON.stringify(options.body) : undefined;
66
- // First attempt
67
- const resp = await fetch(url, { method, headers: { "Content-Type": "application/json" }, body });
68
- if (resp.status !== 402)
69
- return resp;
70
- // ── Parse 402 challenge ──
71
- const challenge = await resp.json();
72
- if (!challenge.x402Version)
73
- return resp;
74
- // Find Solana scheme (scheme === "exact")
75
- const accepts = challenge.accepts || [];
76
- const scheme = accepts.find((a) => a.scheme === "exact" && a.network?.startsWith("solana:"));
77
- if (!scheme) {
78
- throw new Error(`No Solana payment scheme found (got: ${JSON.stringify(accepts.map((a) => a.scheme))})`);
77
+ // Build the payment-enabled fetch once, if a key is present and payments aren't
78
+ // force-disabled. Otherwise paid tools fail closed with a clear message.
79
+ let paidFetch = null;
80
+ let paymentInitError = "";
81
+ if (SECRET && !PAYMENTS_DISABLED) {
82
+ try {
83
+ const secretBytes = bs58.decode(SECRET);
84
+ const signer = await createKeyPairSignerFromBytes(secretBytes);
85
+ const scheme = new ExactSvmScheme(signer, { rpcUrl: RPC_URL });
86
+ const client = new x402Client(selectSolanaExact);
87
+ client.register(SOLANA_MAINNET_CAIP2, scheme);
88
+ paidFetch = wrapFetchWithPayment(fetch, client);
89
+ console.error(`TWZRD MCP: auto-pay armed (payer ${signer.address}) caps $${MAX_PER_CALL}/call $${MAX_TOTAL}/session`);
79
90
  }
80
- const amountMicro = parseInt(scheme.amount || "0", 10);
81
- const amountUsdc = amountMicro / 1_000_000;
82
- const payTo = scheme.payTo;
83
- const feePayer = scheme.extra?.feePayer;
84
- const recentBlockhash = scheme.extra?.recentBlockhash;
85
- const usdcMint = scheme.asset;
86
- // ── Run free preflight before paying ──
87
- const preflightResp = await fetch(`${API_BASE}/v1/intel/preflight`, {
88
- method: "POST",
89
- headers: { "Content-Type": "application/json" },
90
- body: JSON.stringify({
91
- seller_wallet: payTo,
92
- resource_name: "MCP Tool Call",
93
- price_usdc: amountUsdc,
94
- agent_intent: "x402_mcp_auto_pay",
95
- }),
96
- });
97
- const preflight = await preflightResp.json();
98
- const card = preflight?.readiness_card || {};
99
- if (card.decision === "block") {
100
- throw new Error(`Preflight BLOCKED payment to ${payTo}: ${(card.caveats || []).join("; ")}`);
91
+ catch (e) {
92
+ paymentInitError = e instanceof Error ? e.message : String(e);
93
+ console.error(`TWZRD MCP: payment init failed — paid tools disabled: ${paymentInitError}`);
101
94
  }
102
- // ── Check spend cap ──
103
- checkSpendCap(amountUsdc);
104
- // ── Build Solana USDC transfer (scheme === "exact") ──
105
- const connection = new Connection("https://api.mainnet-beta.solana.com", "confirmed");
106
- // Get or create the agent's USDC ATA
107
- const agentAta = await getOrCreateAssociatedTokenAccount(connection, agentKeypair, new PublicKey(usdcMint), agentKeypair.publicKey);
108
- // Build transfer instruction
109
- const transferIx = createTransferInstruction(agentAta.address, // source (agent's USDC ATA)
110
- new PublicKey(payTo), // destination (merchant)
111
- agentKeypair.publicKey, // owner
112
- BigInt(amountMicro));
113
- // Build transaction with sponsored feePayer
114
- const feePayerPubkey = new PublicKey(feePayer);
115
- const message = new TransactionMessage({
116
- payerKey: feePayerPubkey,
117
- recentBlockhash,
118
- instructions: [transferIx],
119
- }).compileToV0Message();
120
- const tx = new VersionedTransaction(message);
121
- tx.sign([agentKeypair]);
122
- // Serialize and base64 encode for X-Payment header
123
- const txBytes = tx.serialize();
124
- const paymentHeader = Buffer.from(txBytes).toString("base64");
125
- // ── Record spend ──
126
- dailySpentUsdc += amountUsdc;
127
- // ── Retry with payment header ──
128
- const retryResp = await fetch(url, {
95
+ }
96
+ // ── HTTP: free path is plain fetch; paid path goes through the x402 SDK ───────
97
+ async function twzrdFetch(path, opts) {
98
+ const url = `${API_BASE}${path}`;
99
+ const method = opts?.method || "GET";
100
+ const body = opts?.body ? JSON.stringify(opts.body) : undefined;
101
+ const init = {
129
102
  method,
130
- headers: { "Content-Type": "application/json", "X-Payment": paymentHeader },
103
+ headers: { "Content-Type": "application/json" },
131
104
  body,
132
- });
133
- if (retryResp.status === 402) {
134
- const err = await retryResp.json();
135
- // Refund the spend cap on failure
136
- dailySpentUsdc -= amountUsdc;
137
- throw new Error(`x402 payment failed: ${JSON.stringify(err).slice(0, 200)}`);
105
+ };
106
+ if (opts?.paid) {
107
+ if (!paidFetch) {
108
+ throw new Error(SECRET
109
+ ? `auto-pay unavailable: ${paymentInitError || "payments force-disabled (TWZRD_MCP_PAYMENTS_ENABLED=0)"}`
110
+ : "paid tool requires TWZRD_WALLET_SECRET_KEY (base58 Solana key)");
111
+ }
112
+ return paidFetch(url, init);
138
113
  }
139
- // Log successful payment
140
- console.error(`[twzrd-mcp] paid ${amountUsdc} USDC → ${payTo.slice(0, 8)}.. for ${path} (daily: ${dailySpentUsdc.toFixed(3)}/${DAILY_CAP_USDC})`);
141
- return retryResp;
114
+ return fetch(url, init);
142
115
  }
143
- // ── MCP Server ────────────────────────────────────────────────────────────
144
- const server = new Server({ name: "twzrd-mcp-server", version: "0.1.0" }, { capabilities: { tools: {} } });
116
+ // ── Tools (free vs paid clearly separated; paid tools pass { paid: true }) ───
145
117
  const TOOLS = [
146
- {
147
- name: "quick_trust",
148
- description: "$0.001 quick Solana wallet reputation check. Auto-pays via x402 (Solana USDC). Always runs free preflight first.",
149
- inputSchema: {
150
- type: "object",
151
- properties: {
152
- wallet: { type: "string", description: "Solana wallet address (base58)" },
153
- },
154
- required: ["wallet"],
155
- },
156
- },
157
- {
158
- name: "full_trust",
159
- description: "$0.05 full trust intelligence + signed V6 receipt. Auto-pays via x402. Runs free preflight first.",
160
- inputSchema: {
161
- type: "object",
162
- properties: {
163
- wallet: { type: "string", description: "Solana wallet address (base58)" },
164
- },
165
- required: ["wallet"],
166
- },
167
- },
168
- {
169
- name: "preflight",
170
- description: "Free pre-payment check. No payment needed. Returns readiness_card with allow/warn/block decision.",
171
- inputSchema: {
172
- type: "object",
173
- properties: {
174
- seller_wallet: { type: "string", description: "Seller wallet to evaluate" },
175
- },
176
- required: ["seller_wallet"],
177
- },
178
- },
179
- {
180
- name: "verify_receipt",
181
- description: "Free — verify a TWZRD V6 receipt offline.",
182
- inputSchema: {
183
- type: "object",
184
- properties: {
185
- leaf: { type: "string", description: "Hex keccak256 receipt leaf" },
186
- signature: { type: "string", description: "Ed25519 signature" },
187
- signing_pubkey: { type: "string", description: "Signer pubkey (base58)" },
188
- },
189
- required: ["leaf"],
190
- },
191
- },
192
- {
193
- name: "wallet_lookup",
194
- description: "Free — discover which facilitators and counterparties a Solana wallet has.",
195
- inputSchema: {
196
- type: "object",
197
- properties: {
198
- wallet: { type: "string", description: "Solana wallet address (base58)" },
199
- },
200
- required: ["wallet"],
201
- },
202
- },
118
+ { name: "preflight", description: "FREE pre-payment check. readiness_card with allow/warn/block + trust_score. No payment.", inputSchema: { type: "object", properties: { seller_wallet: { type: "string" }, resource_name: { type: "string" }, price_usdc: { type: "number" } }, required: ["seller_wallet"] } },
119
+ { name: "wallet_lookup", description: "FREE: facilitators + counterparty breadth for a Solana wallet.", inputSchema: { type: "object", properties: { wallet: { type: "string" } }, required: ["wallet"] } },
120
+ { name: "verify_receipt", description: "FREE: verify a TWZRD V6 receipt (leaf/signature/signing_pubkey).", inputSchema: { type: "object", properties: { leaf: { type: "string" }, signature: { type: "string" }, signing_pubkey: { type: "string" } }, required: ["leaf"] } },
121
+ { name: "quick_trust", description: "PAID $0.001 (auto-pay, Solana x402): quick tier+score for a Solana wallet.", inputSchema: { type: "object", properties: { wallet: { type: "string" } }, required: ["wallet"] } },
122
+ { name: "full_trust", description: "PAID $0.05 (auto-pay, Solana x402): full trust intel + signed V6 receipt.", inputSchema: { type: "object", properties: { wallet: { type: "string" }, seller_wallet: { type: "string" } }, required: ["wallet"] } },
203
123
  ];
124
+ const server = new Server({ name: "twzrd-mcp-server", version: "0.2.0" }, { capabilities: { tools: {} } });
204
125
  server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
205
126
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
206
127
  const { name, arguments: args } = request.params;
128
+ const a = (args || {});
207
129
  async function api(path, opts) {
208
- const resp = await twzrdFetch(path, opts);
209
- const text = await resp.text();
210
- if (!resp.ok)
211
- throw new Error(`TWZRD API ${resp.status}: ${text.slice(0, 200)}`);
212
- return text;
130
+ const r = await twzrdFetch(path, opts);
131
+ const t = await r.text();
132
+ if (!r.ok)
133
+ throw new Error(`TWZRD API ${r.status}: ${t.slice(0, 200)}`);
134
+ return t;
213
135
  }
136
+ // NOTE: quick_trust/full_trust BUY intel ON `wallet` — the caller looks a wallet
137
+ // up precisely because they want to know about it (including risky ones). We do
138
+ // NOT gate the purchase on that wallet's own trust score; that would be backwards
139
+ // (you'd be blocked from buying intel on exactly the wallets you most need it for).
140
+ // The `preflight` tool exists separately to vet a SELLER you are about to pay
141
+ // ELSEWHERE. Spend caps + the payment selector are the safety controls here.
214
142
  switch (name) {
215
- case "quick_trust": {
216
- const wallet = String(args?.wallet || "");
217
- if (!wallet)
218
- throw new Error("wallet required");
219
- return { content: [{ type: "text", text: await api(`/v1/intel/quick/${wallet}`) }] };
220
- }
221
- case "full_trust": {
222
- const wallet = String(args?.wallet || "");
223
- if (!wallet)
224
- throw new Error("wallet required");
225
- return { content: [{ type: "text", text: await api(`/v1/intel/trust/${wallet}`) }] };
226
- }
227
- case "preflight": {
228
- return {
229
- content: [{
230
- type: "text",
231
- text: await api("/v1/intel/preflight", { method: "POST", body: { seller_wallet: args?.seller_wallet, resource_name: "MCP Tool Call", price_usdc: 0.05 } }),
232
- }],
233
- };
234
- }
235
- case "verify_receipt": {
236
- return {
237
- content: [{
238
- type: "text",
239
- text: await api("/v1/receipts/verify", { method: "POST", body: { leaf: args?.leaf, signature: args?.signature, signing_pubkey: args?.signing_pubkey } }),
240
- }],
241
- };
242
- }
243
- case "wallet_lookup": {
244
- const wallet = String(args?.wallet || "");
245
- if (!wallet)
246
- throw new Error("wallet required");
247
- return { content: [{ type: "text", text: await api(`/v1/intel/get_facilitator_footprint?wallet=${wallet}`) }] };
248
- }
249
- default:
250
- throw new Error(`Unknown tool: ${name}`);
143
+ case "quick_trust": return { content: [{ type: "text", text: await api(`/v1/intel/quick/${String(a.wallet)}`, { paid: true }) }] };
144
+ case "full_trust": return { content: [{ type: "text", text: await api(`/v1/intel/trust/${String(a.wallet)}${a.seller_wallet ? `?seller_wallet=${a.seller_wallet}` : ""}`, { paid: true }) }] };
145
+ case "preflight": return { content: [{ type: "text", text: await api("/v1/intel/preflight", { method: "POST", body: { seller_wallet: a.seller_wallet, resource_name: a.resource_name || "MCP", price_usdc: a.price_usdc ?? 0.05 } }) }] };
146
+ case "verify_receipt": return { content: [{ type: "text", text: await api("/v1/receipts/verify", { method: "POST", body: { leaf: a.leaf, signature: a.signature, signing_pubkey: a.signing_pubkey } }) }] };
147
+ case "wallet_lookup": return { content: [{ type: "text", text: await api(`/v1/intel/get_facilitator_footprint?wallet=${String(a.wallet)}`) }] };
148
+ default: throw new Error(`Unknown tool: ${name}`);
251
149
  }
252
150
  });
253
- // ── Start ─────────────────────────────────────────────────────────────────
254
151
  const transport = new StdioServerTransport();
255
152
  await server.connect(transport);
256
- console.error(`TWZRD MCP Serveragent ${agentPubkey.slice(0, 8)}.., cap ${SPEND_CAP_USDC}/${DAILY_CAP_USDC} USDC`);
257
- //# sourceMappingURL=index.js.map
153
+ console.error(`TWZRD MCP (Solana x402) paid=${paidFetch ? "enabled" : "disabled"} caps: $${MAX_PER_CALL}/call $${MAX_TOTAL}/session`);
package/package.json CHANGED
@@ -1,43 +1,31 @@
1
1
  {
2
2
  "name": "twzrd-mcp-server",
3
- "version": "0.1.0",
4
- "description": "MCP server for TWZRD Trust API — auto-pay x402, no manual payment handling needed",
3
+ "version": "0.2.0",
4
+ "description": "TWZRD Trust API MCP server with Solana x402 auto-pay (official @x402 SDK, spend-capped, preflight-gated).",
5
5
  "type": "module",
6
+ "bin": { "twzrd-mcp": "./dist/index.js" },
6
7
  "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "bin": {
9
- "twzrd-mcp": "./dist/index.js"
10
- },
11
- "files": [
12
- "dist",
13
- "README.md"
14
- ],
8
+ "files": ["dist", "README.md"],
9
+ "engines": { "node": ">=20" },
10
+ "repository": { "type": "git", "url": "https://github.com/twzrd-sol/wzrd-final.git", "directory": "packages/twzrd-mcp-server" },
11
+ "homepage": "https://intel.twzrd.xyz",
12
+ "keywords": ["mcp", "x402", "solana", "agent", "trust", "twzrd", "reputation"],
15
13
  "scripts": {
16
14
  "build": "tsc",
17
- "prepublishOnly": "tsc",
18
15
  "typecheck": "tsc --noEmit",
19
- "start": "node dist/index.js"
16
+ "prepublishOnly": "npm run build"
20
17
  },
21
- "keywords": [
22
- "x402",
23
- "twzrd",
24
- "mcp",
25
- "trust",
26
- "reputation"
27
- ],
28
- "author": "TWZRD",
29
- "license": "MIT",
30
18
  "dependencies": {
31
- "@modelcontextprotocol/sdk": "^1.29.0",
32
- "@solana/spl-token": "^0.4.14",
33
- "@solana/web3.js": "^1.98.4",
34
- "@x402/core": "^2.16.0",
35
- "@x402/mcp": "^2.16.0",
36
- "bs58": "^6.0.0",
37
- "viem": "^2.53.1",
38
- "zod": "^4.4.3"
19
+ "@modelcontextprotocol/sdk": "^1.0.0",
20
+ "@x402/core": "^2.17.0",
21
+ "@x402/svm": "^2.17.0",
22
+ "@x402/fetch": "^2.17.0",
23
+ "@solana/kit": "^5.1.0",
24
+ "bs58": "^6.0.0"
39
25
  },
40
26
  "devDependencies": {
41
- "typescript": "^5.9.3"
42
- }
27
+ "typescript": "^5.5.0",
28
+ "@types/node": "^22.0.0"
29
+ },
30
+ "license": "MIT"
43
31
  }
package/dist/index.d.ts DELETED
@@ -1,14 +0,0 @@
1
- /**
2
- * TWZRD MCP Server — auto-pay x402 wrapper for TWZRD's Trust API.
3
- *
4
- * Solana x402: the 402 challenge includes a sponsored feePayer + recentBlockhash.
5
- * The MCP builds a USDC transfer, signs with the agent's Solana keypair, retries.
6
- * Always runs free preflight before auto-paying (spend cap enforced).
7
- *
8
- * ENV:
9
- * TWZRD_SOLANA_KEYPAIR — Solana keypair JSON array (from solana config)
10
- * TWZRD_API_URL — Base URL (default: https://intel.twzrd.xyz)
11
- * TWZRD_SPEND_CAP_USDC — Max USDC per call (default: 0.05)
12
- * TWZRD_DAILY_CAP_USDC — Max USDC per day (default: 1.00)
13
- */
14
- export {};
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}