@nonagon-link/mcp 0.3.0 → 0.3.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @nonagon-link/mcp
2
2
 
3
- MCP (Model Context Protocol) server for [NONAGON LINK](https://app.nnglink.ai) — lets AI agents discover paid APIs and pay for them over the [x402 protocol](https://www.x402.org) with **USDC on Solana**, and — when you configure an EVM wallet — with the **official JPYC** on Polygon / Ethereum (**TEST_JPYSC** on Sepolia for testing), and — only when you also set an EVM USDC cap — with **EVM USDC**. A 402 that asks for any other asset, a different network, or a `payTo` outside your allow-list is rejected without signing.
3
+ MCP (Model Context Protocol) server for [NONAGON LINK](https://nnglink.ai) — lets AI agents discover paid APIs and pay for them over the [x402 protocol](https://www.x402.org) with **USDC on Solana**, and — when you configure an EVM wallet — with the **official JPYC** on Polygon / Ethereum (**TEST_JPYSC** on Sepolia for testing), and — only when you also set an EVM USDC cap — with **EVM USDC**. A 402 that asks for any other asset, a different network, or a `payTo` outside your allow-list is rejected without signing.
4
4
 
5
5
  ## Tools
6
6
 
@@ -52,9 +52,9 @@ Use `currency` together with `maxPrice` to set a budget; the tool rejects an unq
52
52
  | Solana mainnet | Polygon (`eip155:137`), Ethereum (`eip155:1`) | JPYC |
53
53
  | Solana devnet | Sepolia (`eip155:11155111`) | TEST_JPYSC (test token) |
54
54
 
55
- 1. Set `NONAGON_EVM_PRIVATE_KEY` to a **dedicated EVM wallet with a small balance** (`0x` + 64 hex). It is only used to sign typed data (the signer cannot sign transactions).
56
- 2. Set `NONAGON_EVM_PAY_TO` to the NONAGON LINK EVM treasury (from the operator or official docs — never copy it from an untrusted 402). Unset = every EVM payment is refused.
57
- 3. Pass `maxPaymentJpy` to `pay_and_call` (at most 4 decimals). Without it a yen 402 is not signed: the tool returns `PAYMENT_EXCEEDS_LIMIT` with `max: null` and the required amount. The ceiling is 100 by default; raise it with `MCP_MAX_PAYMENT_JPY_CAP` (up to 1000). Polygon JPYC listings start at 10 and Ethereum JPYC listings start at 300, so Ethereum ones need a cap of 300 or more.
55
+ 1. Set `NONAGON_EVM_PRIVATE_KEY` to a **dedicated EVM wallet with a small balance** (`0x` + 64 hex). It is only used to sign typed data (the signer cannot sign transactions). It works only when `NONAGON_NETWORK` is Solana mainnet or devnet, which selects the EVM networks in the table above; with any other network the server refuses to start.
56
+ 2. Set `NONAGON_EVM_PAY_TO` to the NONAGON LINK EVM treasury (see [NONAGON LINK payees](#nonagon-link-payees) — never copy it from an untrusted 402). Unset = every EVM payment is refused.
57
+ 3. Pass `maxPaymentJpy` to `pay_and_call` (at most 4 decimals). Without it a yen 402 is not signed: the tool returns `PAYMENT_EXCEEDS_LIMIT` with `max: null` and the required amount. The ceiling is 100 by default; raise it with `MCP_MAX_PAYMENT_JPY_CAP` (100–1000; below 100 the server does not start). Polygon JPYC listings start at 1 and Ethereum JPYC listings start at 300, so Ethereum ones need a cap of 300 or more. Payments from 1 Polygon JPYC are supported from 0.3.2; 0.3.1 and earlier require at least 10.
58
58
 
59
59
  Before signing, the server checks that the 402's network, asset (the pinned JPYC contract), EIP-712 domain, amount range, `exact` + `eip3009` method, `maxTimeoutSeconds` (≤ 300) and `payTo` all match; otherwise it returns `PAYMENT_REQUIREMENT_REJECTED` without signing. Without an EVM wallet a JPYC listing returns `EVM_WALLET_NOT_CONFIGURED`. EVM USDC is covered in [Paying in EVM USDC](#paying-in-evm-usdc).
60
60
 
@@ -97,11 +97,22 @@ The cap is checked again right before signing, so a call that bypasses the tool'
97
97
 
98
98
  ### Payment status
99
99
 
100
+ NONAGON LINK can reject an unsigned request before issuing a nonce: payment-option policy is checked first (`409 PAYMENT_OPTION_DISABLED` / `503 PAYMENT_OPTIONS_UNAVAILABLE`), then EVM native readiness. Gas uses POL on Polygon or ETH on Ethereum / Base, separately from USDC / JPYC. A readiness snapshot does not reserve a USD budget or guarantee a later settlement.
101
+
102
+ | HTTP | Code | Fixed message |
103
+ |---|---|---|
104
+ | 503 | `EVM_NATIVE_BALANCE_INSUFFICIENT` | Native gas balance is insufficient |
105
+ | 503 | `EVM_NATIVE_READINESS_UNAVAILABLE` | Native gas readiness is unavailable |
106
+ | 503 | `EVM_GAS_LIMIT_EXCEEDED` | Estimated gas exceeds the supported limit |
107
+ | 503 | `EVM_TRANSACTION_ESTIMATE_UNAVAILABLE` | Gas estimation is unavailable |
108
+
109
+ Existing `GAS_LIMIT_EXCEEDED` is the USD per-transaction cap, distinct from the EVM gas quantity limit. `GAS_ESTIMATE_UNAVAILABLE`, `DAILY_GAS_CAP`, `GAS_BUDGET_UNAVAILABLE`, `TX_TIMEOUT`, `TX_FAILED` and `EVM_SETTLE_FAILED` remain. The MCP classifies a request that sent no signed payment as `not_paid`; after submission it does not infer non-payment from any HTTP status or error code, including these 503 errors.
110
+
100
111
  | `paymentStatus` | Meaning | What to do |
101
112
  |---|---|---|
102
113
  | `not_paid` | No payment was sent (rejected 402, limit exceeded, not configured, error before signing) | Fix the cause and retry |
103
114
  | `paid` | The paid request's response carried a successful receipt (even if the API itself then returned an error) | Retrying is a new payment |
104
- | `unknown` | A signed payment was sent but the result is not confirmed (timeout, connection loss, error response, missing receipt). The response body is **not** trusted — the host could claim anything | **Do not retry automatically** (a retry signs a new authorization and can pay twice). For EVM payments (JPYC and EVM USDC) the response includes `authorization` (`network`, `asset`, `from`, `nonce`, `validBefore`): call `authorizationState(from, nonce)` on the token contract. It can never execute only after `validBefore` has passed and `authorizationState` is `false`. `reportedTransaction`, if any, is the host's unverified claim |
115
+ | `unknown` | A signed payment was sent but the result is not confirmed (timeout, connection loss, error response, missing receipt). The response body is **not** trusted — the host could claim anything | **Do not retry automatically** (a retry signs a new authorization and can pay twice). For EVM payments (JPYC and EVM USDC) the response includes `authorization` (`network`, `asset`, `from`, `nonce`, `validBefore`): call `authorizationState(from, nonce)` on the token contract. It can never execute only after `validBefore` has passed and `authorizationState` is `false`. `reportedTransaction`, if any, is the host's unverified claim: independently check its receipt on the saved network and require `transactionHash` to equal the requested hash before reading status. A missing / different-hash receipt does not prove non-payment. Keep the original authorization lookup fields and check again after `validBefore`; a false state before expiry is insufficient. Do not reuse the authorization or automatically create another payment |
105
116
 
106
117
  Payments made with the EVM wallet appear in `get_payment_history` / `get_spending` as the `ethereum` wallet. For an EVM payment, **a missing history row does not prove the authorization was not executed** (the server may not have recorded a failed payment, and anyone holding the authorization can execute it): when `paymentStatus` is `unknown`, check `authorizationState` as described above instead of retrying after looking at the history.
107
118
 
@@ -114,31 +125,42 @@ Add to your MCP client config (e.g. `.claude/settings.json` or `claude_desktop_c
114
125
  "mcpServers": {
115
126
  "nonagon-link": {
116
127
  "command": "npx",
117
- "args": ["-y", "--ignore-scripts", "@nonagon-link/mcp@0.3.0"],
128
+ "args": ["-y", "--ignore-scripts", "@nonagon-link/mcp@0.3.2"],
118
129
  "env": {
119
130
  "NONAGON_PRIVATE_KEY": "<Base58 Solana secret key>",
120
131
  "NONAGON_LINK_BASE_URL": "https://api.nnglink.ai",
121
- "NONAGON_PAY_TO": "<402 payTo — NONAGON LINK platform wallet>"
132
+ "NONAGON_PAY_TO": "8yXpNyyPg9iGdMST8BRyz7HEJVbQG81VP6kHBCKXrdH8"
122
133
  }
123
134
  }
124
135
  }
125
136
  }
126
137
  ```
127
138
 
128
- > **Always pin an exact version** (`@nonagon-link/mcp@0.3.0`). Never use an unversioned `@nonagon-link/mcp` — your private key is passed to the process environment, so an unpinned install would expose it to whatever the latest published version is. `--ignore-scripts` additionally prevents dependency install scripts from running with your environment.
139
+ > **Always pin an exact version** (`@nonagon-link/mcp@0.3.2`). Never use an unversioned `@nonagon-link/mcp` — your private key is passed to the process environment, so an unpinned install would expose it to whatever the latest published version is. `--ignore-scripts` additionally prevents dependency install scripts from running with your environment.
129
140
  >
130
- > **Set `NONAGON_PAY_TO`** to the NONAGON LINK platform wallet. Obtain the platform wallet from the operator or official docs — do not copy `payTo` from an untrusted 402. Unset = `pay_and_call` denies every payment.
141
+ > **Set `NONAGON_PAY_TO`** to the NONAGON LINK Solana platform wallet (see [NONAGON LINK payees](#nonagon-link-payees)) — do not copy `payTo` from an untrusted 402. Unset = every **Solana USDC** payment is refused. EVM payments (JPYC, EVM USDC) are allowed separately by `NONAGON_EVM_PAY_TO`; unset, every EVM payment is refused.
142
+
143
+ ### NONAGON LINK payees
144
+
145
+ The `payTo` values NONAGON LINK uses (public: they appear in every 402). Put them in the allow-lists:
146
+
147
+ | Environment | `NONAGON_PAY_TO` (Solana USDC) | `NONAGON_EVM_PAY_TO` (JPYC / EVM USDC) |
148
+ |---|---|---|
149
+ | Production (Solana mainnet; Ethereum / Polygon / Base) | `8yXpNyyPg9iGdMST8BRyz7HEJVbQG81VP6kHBCKXrdH8` | `0x7b689c9b29e5e51700f19d4bb02b382fb418f34d` |
150
+ | Testing (Solana devnet; Sepolia / Amoy / Base Sepolia) | `6JdW8xNvXrghY7acKXzMn2pJoK88g6nnAVU3YNo1YiF8` | `0xcaeb3ef5dcea1557765323379a292fc6b4011831` |
151
+
152
+ The current values are also listed at https://nnglink.ai/docs/mcp.
131
153
 
132
154
  For stricter isolation, install once and reference the binary directly:
133
155
 
134
156
  ```bash
135
- npm install -g @nonagon-link/mcp@0.3.0
157
+ npm install -g @nonagon-link/mcp@0.3.2
136
158
  ```
137
159
 
138
160
  ```json
139
161
  {
140
162
  "mcpServers": {
141
- "nonagon-link": { "command": "nonagon-mcp", "env": { "NONAGON_PRIVATE_KEY": "...", "NONAGON_PAY_TO": "<402 payTo>" } }
163
+ "nonagon-link": { "command": "nonagon-mcp", "env": { "NONAGON_PRIVATE_KEY": "...", "NONAGON_PAY_TO": "8yXpNyyPg9iGdMST8BRyz7HEJVbQG81VP6kHBCKXrdH8" } }
142
164
  }
143
165
  }
144
166
  ```
@@ -149,12 +171,12 @@ npm install -g @nonagon-link/mcp@0.3.0
149
171
  |---|---|---|
150
172
  | `NONAGON_PRIVATE_KEY` | ✅ | Agent's Solana secret key (Base58). Used to sign USDC payments |
151
173
  | `NONAGON_NETWORK` | — | CAIP-2 network id. Defaults to Solana mainnet. 402 `network` must match |
152
- | `NONAGON_PAY_TO` | For `pay_and_call` | Comma-separated Solana addresses allowed as 402 `payTo` (platform wallet). **Unset = deny all payments** |
174
+ | `NONAGON_PAY_TO` | For Solana `pay_and_call` | Comma-separated Solana addresses allowed as 402 `payTo` (platform wallet). **Unset = every Solana USDC payment is refused** (EVM payments are governed by `NONAGON_EVM_PAY_TO`) |
153
175
  | `NONAGON_USDC_MINT` | — | Override USDC mint **only for unknown `NONAGON_NETWORK`**. Known mainnet/devnet always use the built-in USDC mint |
154
176
  | `MCP_MAX_PAYMENT_USDC_CAP` | — | Raise the `maxPaymentUsdc` (Solana USDC) ceiling (0.1–10, decimal notation, at most 6 decimals). Default 0.100. Does not affect EVM USDC |
155
- | `NONAGON_EVM_PRIVATE_KEY` | For JPYC / EVM USDC / EVM history | EVM wallet key (`0x` + 64 hex) used to sign EVM payments (JPYC; EVM USDC when `MCP_MAX_PAYMENT_EVM_USDC_CAP` is set) and the EIP-712 `AgentChallenge` that reads the EVM wallet's payment history and spending. Unset = Solana USDC only. Validated at startup; the value is never logged or returned |
156
- | `NONAGON_EVM_PAY_TO` | For JPYC / EVM USDC | Comma-separated EVM addresses allowed as the EVM 402 `payTo` (NONAGON LINK EVM treasury). **Unset = deny all EVM payments** |
157
- | `MCP_MAX_PAYMENT_JPY_CAP` | — | Raise the `maxPaymentJpy` ceiling (100–1000, decimal notation, at most 4 decimals). Default 100 |
177
+ | `NONAGON_EVM_PRIVATE_KEY` | For JPYC / EVM USDC / EVM history | EVM wallet key (`0x` + 64 hex) used to sign EVM payments (JPYC; EVM USDC when `MCP_MAX_PAYMENT_EVM_USDC_CAP` is set) and the EIP-712 `AgentChallenge` that reads the EVM wallet's payment history and spending. Unset = Solana USDC only. Requires `NONAGON_NETWORK` to be Solana mainnet or devnet (otherwise the server refuses to start). Validated at startup; the value is never logged or returned |
178
+ | `NONAGON_EVM_PAY_TO` | For JPYC / EVM USDC | Comma-separated EVM addresses allowed as the EVM 402 `payTo` (NONAGON LINK EVM treasury). **Unset = every EVM payment is refused** (Solana USDC payments are governed by `NONAGON_PAY_TO`) |
179
+ | `MCP_MAX_PAYMENT_JPY_CAP` | — | Raise the `maxPaymentJpy` ceiling (100–1000, decimal notation, at most 4 decimals; below 100 the server does not start). Default 100. Ethereum JPYC listings need 300 or more |
158
180
  | `MCP_MAX_PAYMENT_EVM_USDC_CAP` | For EVM USDC | The `maxPaymentEvmUsdc` ceiling and the switch for EVM USDC (range from the pinned USDC prices of the network family — 2–10 today; decimal notation, at most 6 decimals). **Unset = EVM USDC is never paid**. Requires `NONAGON_NETWORK` to be Solana mainnet or devnet |
159
181
  | `NONAGON_LINK_BASE_URL` | For `search_listings` / `get_payment_history` / `get_spending` | NONAGON LINK API base URL (e.g. `https://api.nnglink.ai`). `https` only; `http` allowed for `localhost` in local development. `pay_and_call` does not require it |
160
182
  | `MCP_AUTH_TOKEN` | HTTP mode only | Bearer token for Streamable HTTP transport (32-byte random, base64url or hex) |
@@ -174,8 +196,8 @@ npm install -g @nonagon-link/mcp@0.3.0
174
196
 
175
197
  ## Documentation
176
198
 
177
- - Setup & verification guide: https://app.nnglink.ai/docs/mcp
178
- - Agent developer guide: https://app.nnglink.ai/docs/agent
199
+ - Setup & verification guide: https://nnglink.ai/docs/mcp
200
+ - Agent developer guide: https://nnglink.ai/docs/agent
179
201
 
180
202
  ## License
181
203
 
package/dist/server.js CHANGED
@@ -74,11 +74,11 @@ var YEN_TOKEN_FULL_RANGE = {
74
74
  listingPriceRange: [0.1, 1e3]
75
75
  };
76
76
  var JPYC_POLYGON_RANGE = {
77
- minAmount: 10000000000000000000n,
78
- // 10 JPYC
77
+ minAmount: 1000000000000000000n,
78
+ // 1 JPYC
79
79
  maxAmount: 1000000000000000000000n,
80
80
  // 1000 JPYC
81
- listingPriceRange: [10, 1e3],
81
+ listingPriceRange: [1, 1e3],
82
82
  recordableAmountRange: [0.1, 1e3]
83
83
  };
84
84
  var JPYC_ETH_MAINNET_RANGE = {
@@ -90,7 +90,9 @@ var JPYC_ETH_MAINNET_RANGE = {
90
90
  };
91
91
  var MAINNET_JPYC_ADDRESS = "0xe7c3d8c9a439fede00d2600032d5db0be71c3c29";
92
92
  var SEPOLIA_TEST_JPYSC_ADDRESS = "0x307cba674f0fe9a5a5b084dd58006eb604a24025";
93
- var JPYC_OFFICIAL_EVIDENCE = "issue #1705 \u8981\u4EF6\u4ED8\u9332 A (2026-07-15 \u30AA\u30F3\u30C1\u30A7\u30FC\u30F3\u691C\u8A3C: impl 0xafac17fc..d2e \u306B EIP-3009 selector e3ee160e \u5B9F\u5728 / name=JPY Coin / decimals=18)\u3002domain version \u306F PR2 \u5B9F\u8A3C\u78BA\u5B9A\u30BF\u30B9\u30AF\u3067 tx hash \u306B\u66F4\u65B0";
93
+ var JPYC_APPENDIX_A_EVIDENCE = "issue #1705 \u8981\u4EF6\u4ED8\u9332 A (2026-07-15 \u30AA\u30F3\u30C1\u30A7\u30FC\u30F3\u691C\u8A3C: impl 0xafac17fc..d2e \u306B EIP-3009 selector e3ee160e \u5B9F\u5728 / name=JPY Coin / decimals=18)";
94
+ var JPYC_ETH_MAINNET_EVIDENCE = `${JPYC_APPENDIX_A_EVIDENCE}\u3002domain version \u306F Ethereum mainnet \u306E\u5B9F tx \u3067\u672A\u89B3\u6E2C`;
95
+ var JPYC_POLYGON_EVIDENCE = `${JPYC_APPENDIX_A_EVIDENCE}\u3002domain { JPY Coin, 1 } \u306F 2026-10-05 \u672C\u756A Polygon \u5B9F tx 0xb8e87e92c2000b7922aa115f14b7a0aaf7a1699444d6ecd15a8ab50801f086b4 (block 94995641, transferWithAuthorization \u6210\u529F / 10 JPYC / issue #2056) \u3067\u5B9F\u8A3C`;
94
96
  var EVM_ASSET_PINS = {
95
97
  "eip155:1": {
96
98
  usdc: {
@@ -106,7 +108,7 @@ var EVM_ASSET_PINS = {
106
108
  eip712: { name: "JPY Coin", version: "1" },
107
109
  decimals: 18,
108
110
  currency: "JPYC",
109
- pinEvidence: JPYC_OFFICIAL_EVIDENCE,
111
+ pinEvidence: JPYC_ETH_MAINNET_EVIDENCE,
110
112
  ...JPYC_ETH_MAINNET_RANGE
111
113
  }
112
114
  },
@@ -142,7 +144,7 @@ var EVM_ASSET_PINS = {
142
144
  eip712: { name: "JPY Coin", version: "1" },
143
145
  decimals: 18,
144
146
  currency: "JPYC",
145
- pinEvidence: JPYC_OFFICIAL_EVIDENCE,
147
+ pinEvidence: JPYC_POLYGON_EVIDENCE,
146
148
  ...JPYC_POLYGON_RANGE
147
149
  }
148
150
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nonagon-link/mcp",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "NONAGON LINK MCP server — let AI agents discover and pay for APIs with USDC (x402)",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",