@forgemeshlabs/x402-notary-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/LICENSE +21 -0
- package/README.md +121 -0
- package/index.js +243 -0
- package/package.json +54 -0
- package/server.json +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ForgeMesh Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# x402 Notary — Cryptographic Receipts for AI Outputs
|
|
2
|
+
|
|
3
|
+
*A [ForgeMesh Labs](https://forgemesh.io) product — the notary of the x402 agent economy.*
|
|
4
|
+
|
|
5
|
+
**Prove what your AI said, when it said it, and which model said it.**
|
|
6
|
+
|
|
7
|
+
Every AI output is just text. There's no proof a specific model produced a specific response at a specific time — and as agents start hiring other agents, that trust gap gets expensive. x402 Notary closes it: submit any inference, pay **$0.001** in USDC (automatic, via [x402](https://x402.org) on Base — no API key, no account), and get back a **signed, timestamped, chain-anchored receipt** that anyone can verify, free, forever.
|
|
8
|
+
|
|
9
|
+
> **We notarize the hash, not your secrets.** Your prompt and response are hashed and signed — never stored. Private signed receipts, publicly anchored by batch root on Base.
|
|
10
|
+
|
|
11
|
+
## Quick start (Claude Desktop / Claude Code / any MCP client)
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"x402-notary": {
|
|
17
|
+
"command": "npx",
|
|
18
|
+
"args": ["-y", "@forgemeshlabs/x402-notary-mcp"],
|
|
19
|
+
"env": {
|
|
20
|
+
"WALLET_PRIVATE_KEY": "0x..."
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`WALLET_PRIVATE_KEY` is a **dedicated low-balance Base wallet** for x402 micropayments — never your primary wallet. $1 of USDC notarizes 1,000 outputs.
|
|
28
|
+
|
|
29
|
+
**Verification needs no wallet at all.** Skip the `env` block entirely and you can still verify receipts, inspect attestations, and read live stats.
|
|
30
|
+
|
|
31
|
+
## Tools
|
|
32
|
+
|
|
33
|
+
| Tool | Cost | What it does |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `notarize_inference` | $0.001 | Signed receipt for one `{prompt, response, model_id}` |
|
|
36
|
+
| `notarize_batch` | $0.005 | Up to 20 receipts in one call — built for audit trails |
|
|
37
|
+
| `verify_attestation` | **free** | Check any receipt: signature, content hash, Merkle proof |
|
|
38
|
+
| `get_receipt` | **free** | Fetch the public proof material for an attestation |
|
|
39
|
+
| `notary_stats` | **free** | Live volume, top models, anchored batches |
|
|
40
|
+
| `notary_pubkey` | **free** | The notary's Ed25519 key — verify receipts fully offline |
|
|
41
|
+
|
|
42
|
+
## What a receipt proves
|
|
43
|
+
|
|
44
|
+
When you notarize an inference you get an attestation:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"attestation_id": "att_64d22f5f5c95d0e759ad54dc",
|
|
49
|
+
"content_hash": "sha256 of {prompt, response, model_id, timestamp}",
|
|
50
|
+
"signature": "Ed25519 — verifiable offline against the public notary key",
|
|
51
|
+
"notarized_at": "2026-07-03T02:47:11.000Z",
|
|
52
|
+
"anchor": { "status": "sealed", "merkle_root": "…", "proof": ["…"] }
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
That's proof of three things:
|
|
57
|
+
|
|
58
|
+
1. **Existence** — this exact content existed at this exact time.
|
|
59
|
+
2. **Integrity** — change one character of the prompt or response and verification fails.
|
|
60
|
+
3. **Independence** — signatures verify offline with the published key; Merkle roots anchor batches on Base. You don't have to trust the notary's word after the fact.
|
|
61
|
+
|
|
62
|
+
## Verify anything, free, from anywhere
|
|
63
|
+
|
|
64
|
+
Any agent (or human, or CI job) can check a receipt before acting on the output behind it:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
curl -s https://notary.forgemesh.io/api/verify \
|
|
68
|
+
-H 'content-type: application/json' \
|
|
69
|
+
-d '{"attestation_id":"att_…","prompt":"…","response":"…","model_id":"openai/gpt-5"}'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`"valid": true` means the content matches the notarized hash **and** the notary's Ed25519 signature checks out. Tampered content is rejected with the exact failing check.
|
|
73
|
+
|
|
74
|
+
## When should an agent notarize?
|
|
75
|
+
|
|
76
|
+
Not every call — the outputs that matter:
|
|
77
|
+
|
|
78
|
+
- **Agent-to-agent handoffs** — prove what you passed downstream came from this model, unmodified
|
|
79
|
+
- **Paid deliverables** — research, reports, recommendations someone is paying for
|
|
80
|
+
- **Compliance & audit trails** — decisions that affect money, legal exposure, or reputation
|
|
81
|
+
- **Dispute prevention** — "this is exactly what was generated, at exactly this time"
|
|
82
|
+
- **Marketplace reputation** — build a public, verifiable reliability trail for your agent or service
|
|
83
|
+
|
|
84
|
+
Casual chat and scratchpad reasoning don't need receipts. Externalized outputs do.
|
|
85
|
+
|
|
86
|
+
## Privacy, by design
|
|
87
|
+
|
|
88
|
+
- Raw prompts, responses, and metadata are **not persisted** — the notary computes the hash, signs it, and discards the content.
|
|
89
|
+
- Receipts contain proof material only: hash, signature, timestamps, model id, Merkle proof.
|
|
90
|
+
- Only Merkle **batch roots** are anchored on-chain. Your content never touches a public chain.
|
|
91
|
+
- Verification works by *you* supplying your original content — the notary can't reveal what it never kept.
|
|
92
|
+
|
|
93
|
+
## How payment works
|
|
94
|
+
|
|
95
|
+
No signup, no API key, no subscription. The first request returns an HTTP 402 challenge; your MCP client signs a USDC payment authorization (EIP-3009) and retries. Settlement happens on Base in seconds and the receipt lands in the same response — including the payment transaction hash under `_payment`.
|
|
96
|
+
|
|
97
|
+
## Direct API
|
|
98
|
+
|
|
99
|
+
Prefer raw HTTP? The full agent-readable surface:
|
|
100
|
+
|
|
101
|
+
- `https://notary.forgemesh.io/llms.txt` — one-page summary for agents
|
|
102
|
+
- `https://notary.forgemesh.io/openapi.json` — OpenAPI 3.1 with x402 payment metadata
|
|
103
|
+
- `https://notary.forgemesh.io/.well-known/x402.json` — x402 discovery manifest
|
|
104
|
+
|
|
105
|
+
## FAQ
|
|
106
|
+
|
|
107
|
+
**Is my prompt stored anywhere?** No. The hash is computed, signed, and the raw text is discarded. This is the default and only mode.
|
|
108
|
+
|
|
109
|
+
**Do I need an account or API key?** No. x402 payments are the only credential.
|
|
110
|
+
|
|
111
|
+
**What does verification cost?** Nothing, for anyone, forever. Charging to verify would defeat the point of a trust primitive.
|
|
112
|
+
|
|
113
|
+
**What chain and token?** USDC on Base mainnet (`eip155:8453`).
|
|
114
|
+
|
|
115
|
+
**Can I verify receipts without contacting the notary?** Yes — fetch the Ed25519 public key once (`notary_pubkey`) and verify signatures offline.
|
|
116
|
+
|
|
117
|
+
**Why "x402 Notary"?** [x402](https://x402.org) is the open protocol that lets AI agents pay for services in USDC over plain HTTP — and this is its notary: the attestation layer agents use to prove and verify each other's outputs before money or reputation moves on them.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
Built by [ForgeMesh Labs](https://forgemesh.io) · Powered by the [x402 protocol](https://x402.org) · MIT License
|
package/index.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const { Server } = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
|
+
const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
const { CallToolRequestSchema, ListToolsRequestSchema } = require("@modelcontextprotocol/sdk/types.js");
|
|
7
|
+
const { x402Client, x402HTTPClient } = require("@x402/core/client");
|
|
8
|
+
const { ExactEvmScheme } = require("@x402/evm/exact/client");
|
|
9
|
+
const { toClientEvmSigner } = require("@x402/evm");
|
|
10
|
+
const { privateKeyToAccount } = require("viem/accounts");
|
|
11
|
+
const { createPublicClient, http } = require("viem");
|
|
12
|
+
const { base } = require("viem/chains");
|
|
13
|
+
|
|
14
|
+
const VERSION = "0.1.0";
|
|
15
|
+
const BASE_URL = (process.env.NOTARY_BASE_URL || "https://notary.forgemesh.io").replace(/\/$/, "");
|
|
16
|
+
const BASE_RPC_URL = process.env.BASE_RPC_URL || "https://mainnet.base.org";
|
|
17
|
+
|
|
18
|
+
const RECORD_PROPS = {
|
|
19
|
+
prompt: { type: "string", description: "The exact prompt/input that was sent to the model" },
|
|
20
|
+
response: { type: "string", description: "The exact model output you want a receipt for" },
|
|
21
|
+
model_id: { type: "string", description: "Model identifier, e.g. 'openai/gpt-5' or 'claude-fable-5'" },
|
|
22
|
+
client_timestamp: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Optional ISO-8601 time the inference ran. Included in the content hash if provided.",
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const TOOLS = [
|
|
29
|
+
{
|
|
30
|
+
name: "notarize_inference",
|
|
31
|
+
description:
|
|
32
|
+
"Get a cryptographic receipt for one AI inference. Returns a signed Ed25519 attestation, sha256 content hash, and Merkle chain-anchor status for {prompt, response, model_id}. The notary does NOT store your prompt or response — only the hash is retained. Costs $0.001 USDC via x402 (requires WALLET_PRIVATE_KEY).",
|
|
33
|
+
inputSchema: {
|
|
34
|
+
type: "object",
|
|
35
|
+
properties: RECORD_PROPS,
|
|
36
|
+
required: ["prompt", "response", "model_id"],
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "notarize_batch",
|
|
41
|
+
description:
|
|
42
|
+
"Notarize up to 20 AI inferences in one call — one signed attestation per record. Ideal for audit trails and agent pipelines. Costs $0.005 USDC via x402 (requires WALLET_PRIVATE_KEY).",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: "object",
|
|
45
|
+
properties: {
|
|
46
|
+
records: {
|
|
47
|
+
type: "array",
|
|
48
|
+
description: "1-20 records of {prompt, response, model_id, client_timestamp?}",
|
|
49
|
+
items: { type: "object", properties: RECORD_PROPS, required: ["prompt", "response", "model_id"] },
|
|
50
|
+
minItems: 1,
|
|
51
|
+
maxItems: 20,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
required: ["records"],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "verify_attestation",
|
|
59
|
+
description:
|
|
60
|
+
"FREE — verify any attestation issued by the notary. Supply the attestation_id plus either the original content ({prompt, response, model_id}) or its content_hash. Returns the Ed25519 signature check, hash comparison, and a Merkle inclusion proof once the batch is sealed. No wallet needed.",
|
|
61
|
+
inputSchema: {
|
|
62
|
+
type: "object",
|
|
63
|
+
properties: {
|
|
64
|
+
attestation_id: { type: "string", description: "Attestation id (att_…) from a receipt" },
|
|
65
|
+
...RECORD_PROPS,
|
|
66
|
+
content_hash: {
|
|
67
|
+
type: "string",
|
|
68
|
+
description: "Alternative to supplying full content: the sha256 content hash to compare directly",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
required: ["attestation_id"],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "get_receipt",
|
|
76
|
+
description:
|
|
77
|
+
"FREE — fetch the public receipt for an attestation: content hash, model, timestamps, Ed25519 signature, and Merkle anchor proof. Raw prompt/response are never stored, so receipts contain proof material only. No wallet needed.",
|
|
78
|
+
inputSchema: {
|
|
79
|
+
type: "object",
|
|
80
|
+
properties: {
|
|
81
|
+
attestation_id: { type: "string", description: "Attestation id (att_…)" },
|
|
82
|
+
},
|
|
83
|
+
required: ["attestation_id"],
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "notary_stats",
|
|
88
|
+
description:
|
|
89
|
+
"FREE — live aggregate stats: total notarizations, 24h volume, top models by attestation count, sealed/anchored Merkle batches. No wallet needed.",
|
|
90
|
+
inputSchema: { type: "object", properties: {} },
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "notary_pubkey",
|
|
94
|
+
description:
|
|
95
|
+
"FREE — the notary's Ed25519 public key (base64, raw 32 bytes) for fully offline signature verification. No wallet needed.",
|
|
96
|
+
inputSchema: { type: "object", properties: {} },
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
function buildHttpClient() {
|
|
101
|
+
const key = process.env.WALLET_PRIVATE_KEY;
|
|
102
|
+
if (!key) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
"WALLET_PRIVATE_KEY is not set. Notarization costs $0.001 USDC via x402 — set a dedicated low-balance Base wallet private key (never your primary wallet). Verification tools work without it."
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
const pk = key.startsWith("0x") ? key : "0x" + key;
|
|
108
|
+
const account = privateKeyToAccount(pk);
|
|
109
|
+
const coreClient = new x402Client().register("eip155:*", new ExactEvmScheme(toClientEvmSigner(account)));
|
|
110
|
+
return { httpClient: new x402HTTPClient(coreClient), account };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// x402 derives EIP-3009 validity windows from Date.now; choose a timestamp
|
|
114
|
+
// valid for both Base block time and facilitator wall-clock checks.
|
|
115
|
+
async function createChainTimedPaymentPayload(httpClient, paymentRequired) {
|
|
116
|
+
try {
|
|
117
|
+
const publicClient = createPublicClient({ chain: base, transport: http(BASE_RPC_URL) });
|
|
118
|
+
const block = await publicClient.getBlock();
|
|
119
|
+
const chainNow = Number(block.timestamp);
|
|
120
|
+
const originalNow = Date.now;
|
|
121
|
+
const localNow = Math.floor(originalNow() / 1000);
|
|
122
|
+
const timeout = Number(paymentRequired.accepts?.[0]?.maxTimeoutSeconds || 300);
|
|
123
|
+
const lowerBound = localNow + 30 - timeout;
|
|
124
|
+
const upperBound = chainNow + 600;
|
|
125
|
+
const signingNow = Math.min(Math.max(chainNow, lowerBound), upperBound);
|
|
126
|
+
Date.now = () => signingNow * 1000;
|
|
127
|
+
try {
|
|
128
|
+
return await httpClient.createPaymentPayload(paymentRequired);
|
|
129
|
+
} finally {
|
|
130
|
+
Date.now = originalNow;
|
|
131
|
+
}
|
|
132
|
+
} catch (_) {
|
|
133
|
+
return httpClient.createPaymentPayload(paymentRequired);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function freeFetch(path, init) {
|
|
138
|
+
const res = await fetch(BASE_URL + path, init);
|
|
139
|
+
const raw = await res.text();
|
|
140
|
+
let data;
|
|
141
|
+
try {
|
|
142
|
+
data = JSON.parse(raw);
|
|
143
|
+
} catch (_) {
|
|
144
|
+
data = { raw: raw.slice(0, 500) };
|
|
145
|
+
}
|
|
146
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}: ${JSON.stringify(data).slice(0, 300)}`);
|
|
147
|
+
return data;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function paidPost(ctx, path, body) {
|
|
151
|
+
const { httpClient } = ctx;
|
|
152
|
+
const url = BASE_URL + path;
|
|
153
|
+
const init = { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) };
|
|
154
|
+
const res = await fetch(url, init);
|
|
155
|
+
|
|
156
|
+
if (res.status === 402) {
|
|
157
|
+
let challengeBody;
|
|
158
|
+
try {
|
|
159
|
+
challengeBody = await res.clone().json();
|
|
160
|
+
} catch (_) {}
|
|
161
|
+
const paymentRequired = httpClient.getPaymentRequiredResponse((name) => res.headers.get(name), challengeBody);
|
|
162
|
+
const paymentPayload = await createChainTimedPaymentPayload(httpClient, paymentRequired);
|
|
163
|
+
const paidRes = await fetch(url, {
|
|
164
|
+
...init,
|
|
165
|
+
headers: { ...init.headers, ...httpClient.encodePaymentSignatureHeader(paymentPayload) },
|
|
166
|
+
});
|
|
167
|
+
if (!paidRes.ok) {
|
|
168
|
+
const errBody = await paidRes.text().catch(() => paidRes.statusText);
|
|
169
|
+
throw new Error(`HTTP ${paidRes.status}: ${errBody.slice(0, 200)}`);
|
|
170
|
+
}
|
|
171
|
+
const data = await paidRes.json();
|
|
172
|
+
try {
|
|
173
|
+
const settleResponse = httpClient.getPaymentSettleResponse((name) => paidRes.headers.get(name));
|
|
174
|
+
if (settleResponse && data && typeof data === "object" && !Array.isArray(data)) {
|
|
175
|
+
return { ...data, _payment: settleResponse };
|
|
176
|
+
}
|
|
177
|
+
} catch (_) {}
|
|
178
|
+
return data;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (!res.ok) {
|
|
182
|
+
const errBody = await res.text().catch(() => res.statusText);
|
|
183
|
+
throw new Error(`HTTP ${res.status}: ${errBody.slice(0, 200)}`);
|
|
184
|
+
}
|
|
185
|
+
return res.json();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async function main() {
|
|
189
|
+
let ctx;
|
|
190
|
+
function getPaymentContext() {
|
|
191
|
+
if (!ctx) ctx = buildHttpClient();
|
|
192
|
+
return ctx;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const server = new Server({ name: "x402-notary-mcp", version: VERSION }, { capabilities: { tools: {} } });
|
|
196
|
+
|
|
197
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
198
|
+
|
|
199
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
200
|
+
const { name, arguments: args = {} } = req.params;
|
|
201
|
+
try {
|
|
202
|
+
let data;
|
|
203
|
+
switch (name) {
|
|
204
|
+
case "notarize_inference":
|
|
205
|
+
data = await paidPost(getPaymentContext(), "/api/notarize", args);
|
|
206
|
+
break;
|
|
207
|
+
case "notarize_batch":
|
|
208
|
+
data = await paidPost(getPaymentContext(), "/api/notarize/batch", { records: args.records });
|
|
209
|
+
break;
|
|
210
|
+
case "verify_attestation":
|
|
211
|
+
data = await freeFetch("/api/verify", {
|
|
212
|
+
method: "POST",
|
|
213
|
+
headers: { "Content-Type": "application/json" },
|
|
214
|
+
body: JSON.stringify(args),
|
|
215
|
+
});
|
|
216
|
+
break;
|
|
217
|
+
case "get_receipt":
|
|
218
|
+
data = await freeFetch(`/api/receipt/${encodeURIComponent(args.attestation_id)}`);
|
|
219
|
+
break;
|
|
220
|
+
case "notary_stats":
|
|
221
|
+
data = await freeFetch("/api/stats");
|
|
222
|
+
break;
|
|
223
|
+
case "notary_pubkey":
|
|
224
|
+
data = await freeFetch("/api/pubkey");
|
|
225
|
+
break;
|
|
226
|
+
default:
|
|
227
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
228
|
+
}
|
|
229
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
230
|
+
} catch (e) {
|
|
231
|
+
return { content: [{ type: "text", text: `Error: ${e.message}` }], isError: true };
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const transport = new StdioServerTransport();
|
|
236
|
+
await server.connect(transport);
|
|
237
|
+
console.error(`x402-notary-mcp v${VERSION} ready — ${BASE_URL}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
main().catch((e) => {
|
|
241
|
+
console.error("Fatal:", e.message);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forgemeshlabs/x402-notary-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The notary of the x402 agent economy, by ForgeMesh Labs. Cryptographic receipts for AI outputs: notarize any model inference with a signed Ed25519 attestation, sha256 content hash, and Merkle chain-anchor on Base — $0.001 per call via x402 USDC micropayments. Verification is free and needs no wallet. We notarize the hash, never your prompts.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"x402-notary-mcp": "index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js",
|
|
11
|
+
"README.md",
|
|
12
|
+
"server.json",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"mcpName": "io.github.forgemeshlabs/x402-notary-mcp",
|
|
16
|
+
"scripts": {
|
|
17
|
+
"start": "node index.js"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"model-context-protocol",
|
|
22
|
+
"x402",
|
|
23
|
+
"notary",
|
|
24
|
+
"ai-notarization",
|
|
25
|
+
"attestation",
|
|
26
|
+
"ai-provenance",
|
|
27
|
+
"cryptographic-receipt",
|
|
28
|
+
"verify-ai-output",
|
|
29
|
+
"audit-trail",
|
|
30
|
+
"ed25519",
|
|
31
|
+
"merkle-proof",
|
|
32
|
+
"usdc",
|
|
33
|
+
"base",
|
|
34
|
+
"micropayments",
|
|
35
|
+
"autonomous-agents",
|
|
36
|
+
"agent-trust"
|
|
37
|
+
],
|
|
38
|
+
"author": "ForgeMesh Labs (https://forgemesh.io)",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/forgemeshlabs/x402-notary-mcp.git"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://notary.forgemesh.io",
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=20"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@modelcontextprotocol/sdk": "^1.10.1",
|
|
50
|
+
"@x402/core": "^2.11.0",
|
|
51
|
+
"@x402/evm": "^2.11.0",
|
|
52
|
+
"viem": "^2.0.0"
|
|
53
|
+
}
|
|
54
|
+
}
|
package/server.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.forgemeshlabs/x402-notary-mcp",
|
|
4
|
+
"description": "The notary of the x402 agent economy, by ForgeMesh Labs. Cryptographic receipts for AI outputs: signed Ed25519 attestations, sha256 content hashes, and Merkle chain-anchors on Base for $0.001 per inference via x402 USDC micropayments. Free verification, no wallet needed. We notarize the hash, never your prompts.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"url": "https://github.com/forgemeshlabs/x402-notary-mcp",
|
|
7
|
+
"source": "github"
|
|
8
|
+
},
|
|
9
|
+
"version": "0.1.0",
|
|
10
|
+
"packages": [
|
|
11
|
+
{
|
|
12
|
+
"registryType": "npm",
|
|
13
|
+
"identifier": "@forgemeshlabs/x402-notary-mcp",
|
|
14
|
+
"version": "0.1.0",
|
|
15
|
+
"transport": {
|
|
16
|
+
"type": "stdio"
|
|
17
|
+
},
|
|
18
|
+
"environmentVariables": [
|
|
19
|
+
{
|
|
20
|
+
"name": "WALLET_PRIVATE_KEY",
|
|
21
|
+
"description": "Dedicated low-balance Base wallet private key for x402 USDC micropayments ($1 notarizes 1,000 outputs). Optional — verification tools work without it. Never use your primary wallet.",
|
|
22
|
+
"isRequired": false,
|
|
23
|
+
"isSecret": true,
|
|
24
|
+
"format": "string"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|