mpp32-mcp-server 1.2.4 → 1.4.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/CHANGELOG.md +127 -0
- package/README.md +74 -1
- package/dist/index.js +355 -3
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,133 @@ All notable changes to `mpp32-mcp-server` are documented here. The format
|
|
|
4
4
|
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
|
|
5
5
|
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [1.4.0] - 2026-05-21
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
* **`get_pivx_dao_intelligence` MCP tool — real-time PIVX DAO governance
|
|
12
|
+
intelligence.** Returns active budget proposals with masternode voting
|
|
13
|
+
tallies (Yes/No counts, net yes percentage), budget allocation status,
|
|
14
|
+
network health metrics, and deflation/fee burn analysis. PIVX is a fully
|
|
15
|
+
community-governed cryptocurrency where Masternode owners vote on budget
|
|
16
|
+
proposals every ~30 days (43,200 blocks per superblock cycle, 432,000 PIV
|
|
17
|
+
max monthly budget). Data is sourced live from pivx.org/proposals (HTML
|
|
18
|
+
scraping with structured `data-*` attributes) and the Chainz CryptoID
|
|
19
|
+
blockchain API. Cached for 5 minutes. Free — no payment key required.
|
|
20
|
+
|
|
21
|
+
Parameters:
|
|
22
|
+
- `filter` (optional, enum: `all` | `passing` | `failing`) — filter
|
|
23
|
+
proposals by voting status. Default: `all`.
|
|
24
|
+
- `includeStats` (optional, boolean) — include network stats and deflation
|
|
25
|
+
metrics. Default: `true`.
|
|
26
|
+
|
|
27
|
+
The response includes:
|
|
28
|
+
- **Network Overview:** masternode count, passing threshold (10% of
|
|
29
|
+
masternodes), monthly budget (PIV and USD), budget allocation percentage,
|
|
30
|
+
block height, total/circulating supply.
|
|
31
|
+
- **Deflation Metrics:** unallocated treasury PIV per cycle (never minted),
|
|
32
|
+
annual unallocated estimate, effective inflation reduction percentage,
|
|
33
|
+
proposal submission fee burn (50 PIV per proposal).
|
|
34
|
+
- **Active Proposals:** name, status (passing/failing), funded flag,
|
|
35
|
+
vote counts (yes/no), net yes percentage, monthly and total payment
|
|
36
|
+
amounts (PIV and USD), installments remaining, budget usage percentage,
|
|
37
|
+
and link to proposal details.
|
|
38
|
+
|
|
39
|
+
* **PIVX Governance Oracle catalog entry.** Listed as `curated:pivx-governance`
|
|
40
|
+
in the federated catalog (category: crypto, free, verified). Discoverable
|
|
41
|
+
via `list_mpp32_services` with `q=pivx` or `category=crypto`.
|
|
42
|
+
|
|
43
|
+
* **Backend `/api/governance` endpoints.** Three routes serve the PIVX data:
|
|
44
|
+
`GET /api/governance` (full governance data + deflation), `GET
|
|
45
|
+
/api/governance/proposals?status=passing|failing` (filtered proposals),
|
|
46
|
+
`GET /api/governance/stats` (network stats only). Rate limited to 30
|
|
47
|
+
req/min.
|
|
48
|
+
|
|
49
|
+
* **Frontend `/governance` page** at mpp32.org/governance. Live dashboard
|
|
50
|
+
with proposal cards, vote bars, budget stats, deflation metrics, and an
|
|
51
|
+
explainer on how PIVX governance works.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
* **`server.json` version bumped to 1.4.0** to match the npm release.
|
|
56
|
+
|
|
57
|
+
## [1.3.1] - 2026-05-15
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
|
|
61
|
+
* **Diagnostics tool referenced non-existent `query_intelligence`.** The
|
|
62
|
+
`get_mpp32_diagnostics` "Ready to pay" message told users to try
|
|
63
|
+
`query_intelligence`, which was never a tool name. Now correctly says
|
|
64
|
+
`get_solana_token_intelligence`.
|
|
65
|
+
|
|
66
|
+
* **`protocol` filter missing from `list_mpp32_services`.** The tool
|
|
67
|
+
description and the backend both support filtering by payment protocol
|
|
68
|
+
(x402, tempo, acp, ap2, agtp), but the parameter was never wired
|
|
69
|
+
through. Added `protocol` as an optional enum parameter and forwarded
|
|
70
|
+
it to the backend query string.
|
|
71
|
+
|
|
72
|
+
* **`server.json` version stuck at 1.2.2.** The MCP registry manifest
|
|
73
|
+
was never bumped past 1.2.2, causing the official registry listing to
|
|
74
|
+
advertise the wrong version. Updated to 1.3.1 with all new env vars.
|
|
75
|
+
|
|
76
|
+
* **`server.json` missing `MPP32_PREFERRED_NETWORK` and `MPP32_TIMEOUT_MS`
|
|
77
|
+
environment variables.** Both were supported since 1.2.3 and 1.1.2
|
|
78
|
+
respectively but never declared in the registry manifest.
|
|
79
|
+
|
|
80
|
+
### Added
|
|
81
|
+
|
|
82
|
+
* **README now documents all M32-gated tools.** `get_m32_whale_tracker`,
|
|
83
|
+
`compare_tokens_m32`, and `scan_portfolio_m32` were live in the server
|
|
84
|
+
but missing from the README's tools section.
|
|
85
|
+
|
|
86
|
+
* **README now documents `MPP32_SOLANA_RPC_URL` and `MPP32_TIMEOUT_MS`**
|
|
87
|
+
in the configuration table.
|
|
88
|
+
|
|
89
|
+
## [1.3.0] - 2026-05-14
|
|
90
|
+
|
|
91
|
+
### Added
|
|
92
|
+
|
|
93
|
+
* **Economic Circuit Breakers — infrastructure-level spending guardrails.**
|
|
94
|
+
The first MCP payment server with built-in budget enforcement. No more
|
|
95
|
+
runaway agent bills.
|
|
96
|
+
|
|
97
|
+
- **`manage_agent_budget` tool** — new MCP tool to view, set, or reset
|
|
98
|
+
spending limits directly from Claude, Cursor, or any MCP client.
|
|
99
|
+
Supports three actions:
|
|
100
|
+
- `get`: View current budget status (remaining balance, hourly velocity,
|
|
101
|
+
circuit breaker state, per-service spending breakdown).
|
|
102
|
+
- `set`: Configure `budgetLimitUsd` (total session cap), `velocityLimitUsd`
|
|
103
|
+
(hourly max), and `alertThresholdPercent` (warning threshold).
|
|
104
|
+
- `reset`: Manually clear a tripped circuit breaker so the session can
|
|
105
|
+
resume spending.
|
|
106
|
+
|
|
107
|
+
- **Per-session budget limits** — set a maximum total spend in USD when
|
|
108
|
+
creating a session or at any time via the new `manage_agent_budget` tool.
|
|
109
|
+
When the limit is reached, the circuit breaker trips and all paid calls
|
|
110
|
+
are blocked until manually reset or the budget is increased.
|
|
111
|
+
|
|
112
|
+
- **Velocity (hourly) limits** — cap how fast an agent can spend. Prevents
|
|
113
|
+
infinite-loop scenarios where an agent drains a wallet in minutes.
|
|
114
|
+
|
|
115
|
+
- **Automatic circuit breaker** — trips instantly when budget or velocity
|
|
116
|
+
limits are exceeded. Sticky by design: agents cannot auto-resume spending.
|
|
117
|
+
Requires explicit reset via the MCP tool or API.
|
|
118
|
+
|
|
119
|
+
- **Budget status in every response** — all `call_mpp32_endpoint` and
|
|
120
|
+
`get_solana_token_intelligence` responses now include remaining budget,
|
|
121
|
+
utilization percentage, and circuit breaker state when limits are
|
|
122
|
+
configured.
|
|
123
|
+
|
|
124
|
+
- **Circuit breaker error handling** — when a circuit breaker is tripped,
|
|
125
|
+
the MCP server returns a clear, actionable message explaining what
|
|
126
|
+
happened and how to resume (via `manage_agent_budget`).
|
|
127
|
+
|
|
128
|
+
### Changed
|
|
129
|
+
|
|
130
|
+
* **`formatExecuteSuccess` now includes budget status.** When budget limits
|
|
131
|
+
are configured, successful responses include a one-line budget summary
|
|
132
|
+
(remaining balance and utilization %).
|
|
133
|
+
|
|
7
134
|
## [1.2.4] - 2026-05-11
|
|
8
135
|
|
|
9
136
|
### Fixed
|
package/README.md
CHANGED
|
@@ -33,8 +33,10 @@ MPP32 replaces all of that with one MCP server. Your agent asks for a service by
|
|
|
33
33
|
* Browse a live catalog of over 4,500 paid and free APIs across categories like token intelligence, market data, web search, image generation, embeddings, DeFi analytics, wallet scoring, on chain queries, and trading signals.
|
|
34
34
|
* Pay any provider in the catalog using whichever protocol fits, with settlement that lands in seconds.
|
|
35
35
|
* Run real time Solana token intelligence with alpha scoring, rug risk, whale flow, and 24 hour pump probability.
|
|
36
|
+
* Query live PIVX DAO governance data: active proposals, masternode voting tallies, budget allocation, and network deflation metrics — all free, no payment key needed.
|
|
36
37
|
* Track every call, every dollar settled, and every protocol used from a dashboard at mpp32.org.
|
|
37
38
|
* Get an automatic 20 percent or 40 percent discount on native services for holding M32 once your wallet is verified.
|
|
39
|
+
* Access M32-gated exclusive APIs: Whale Tracker (1M M32), Token Comparison (2.5M M32), and Portfolio Scanner (5M M32) — free for holders, unavailable to non-holders.
|
|
38
40
|
|
|
39
41
|
## Install
|
|
40
42
|
|
|
@@ -98,6 +100,8 @@ Tip: call the `get_mpp32_diagnostics` tool from inside Claude. It probes the API
|
|
|
98
100
|
| `MPP32_SOLANA_PRIVATE_KEY` | Paid x402 calls on Solana | Base58 encoded Solana secret key. Used to sign USDC payments locally. Never leaves your machine. |
|
|
99
101
|
| `MPP32_PRIVATE_KEY` | Paid x402 calls on Base | 0x prefixed EVM private key. Used to sign USDC payments on Base when a provider only accepts EVM. |
|
|
100
102
|
| `MPP32_PREFERRED_NETWORK` | Optional override | When both keys are configured and the challenge advertises multiple networks, force one. Accepts `solana`, `base`, `evm`, or a full CAIP-2 string. |
|
|
103
|
+
| `MPP32_SOLANA_RPC_URL` | Optional | Override the Solana RPC endpoint used to fetch recent blockhashes when building x402 transactions. Defaults to `https://api.mainnet-beta.solana.com`. Set this if you hit public rate limits. |
|
|
104
|
+
| `MPP32_TIMEOUT_MS` | Optional | Request timeout in milliseconds for all outbound API calls. Range 1000 to 300000. Defaults to 30000 (30 seconds). |
|
|
101
105
|
| `MPP32_API_URL` | Custom deployments | Override the API base URL. Defaults to `https://mpp32.org`. |
|
|
102
106
|
|
|
103
107
|
Private keys stay on your machine. They sign payments locally and never travel to MPP32 servers. Provide either or both for paid calls. If both are present and a challenge advertises both networks, EVM is preferred unless `MPP32_PREFERRED_NETWORK` is set; if only one key is configured, that network wins automatically.
|
|
@@ -148,7 +152,76 @@ Real time analysis of any Solana token. Pulls live data from DexScreener, Jupite
|
|
|
148
152
|
{ "token": "BONK" }
|
|
149
153
|
```
|
|
150
154
|
|
|
151
|
-
M32 holders
|
|
155
|
+
M32 holders get tiered discounts (20 percent at 250k, 40 percent at 1M) once SIWS wallet signature verification ships. The discount path is gated off in production until then so it cannot be claimed by spoofing a wallet header. M32 holders also get exclusive access to three token-gated APIs: Whale Tracker (1M M32), Token Comparison (2.5M M32), and Portfolio Scanner (5M M32) — these are live now and require passing your wallet address via the `X-Wallet-Address` header.
|
|
156
|
+
|
|
157
|
+
### `get_m32_whale_tracker`
|
|
158
|
+
|
|
159
|
+
M32-gated whale analysis for any Solana token. Returns top 20 holders, concentration risk, holder distribution, and buy/sell pressure. Requires the caller to hold 1,000,000+ M32 tokens (balance verified on-chain). Free for qualifying holders.
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{ "token": "<mint-address>", "walletAddress": "<your-solana-wallet>" }
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### `compare_tokens_m32`
|
|
166
|
+
|
|
167
|
+
M32-gated head-to-head intelligence comparison of two Solana tokens. Returns side-by-side alpha scores, rug risk, whale activity, volume, liquidity, and a winner verdict. Requires 2,500,000+ M32 tokens.
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{ "tokenA": "<mint-A>", "tokenB": "<mint-B>", "walletAddress": "<your-solana-wallet>" }
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### `scan_portfolio_m32`
|
|
174
|
+
|
|
175
|
+
M32-gated full wallet portfolio scan. Discovers all SPL tokens in a wallet, runs intelligence on top holdings, and returns per-token analysis with aggregate risk metrics. Requires 5,000,000+ M32 tokens.
|
|
176
|
+
|
|
177
|
+
```json
|
|
178
|
+
{ "wallet": "<wallet-to-scan>", "walletAddress": "<your-solana-wallet>" }
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### `get_pivx_dao_intelligence`
|
|
182
|
+
|
|
183
|
+
Real-time PIVX DAO governance intelligence. Returns active budget proposals with masternode voting tallies, budget allocation status, network deflation metrics, and masternode network health. PIVX is a fully community-governed cryptocurrency where Masternode owners vote on budget proposals every ~30 days. Data sourced live from pivx.org/proposals and the PIVX blockchain. Free — no payment key required.
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{ "filter": "all" }
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
{ "filter": "passing", "includeStats": true }
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Two parameters:
|
|
194
|
+
|
|
195
|
+
* **filter** (optional) — `all` (default), `passing`, or `failing`. Filters proposals by voting status.
|
|
196
|
+
* **includeStats** (optional, default true) — include network overview and deflation metrics alongside proposals.
|
|
197
|
+
|
|
198
|
+
The response includes a network overview (masternode count, passing threshold, monthly budget in PIV and USD, budget allocation percentage, block height, supply stats), deflation metrics (unallocated treasury PIV that are never minted, effective inflation reduction, proposal fee burn), and all active proposals with vote counts, payment amounts, installments, and links.
|
|
199
|
+
|
|
200
|
+
View the governance dashboard at [mpp32.org/governance](https://mpp32.org/governance).
|
|
201
|
+
|
|
202
|
+
### `manage_agent_budget`
|
|
203
|
+
|
|
204
|
+
View, set, or reset the economic circuit breaker for your agent session. Prevents runaway spending with infrastructure-level budget enforcement.
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{ "action": "get" }
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{ "action": "set", "budgetLimitUsd": 10.0, "velocityLimitUsd": 1.0, "alertThresholdPercent": 80 }
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{ "action": "reset" }
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Three actions:
|
|
219
|
+
|
|
220
|
+
* **get** returns current budget status: remaining balance, hourly velocity, circuit breaker state, and per-service spending breakdown.
|
|
221
|
+
* **set** configures `budgetLimitUsd` (max total session spend), `velocityLimitUsd` (max spend per hour), and `alertThresholdPercent` (warn at this percentage of budget used). All three are optional and can be set independently.
|
|
222
|
+
* **reset** clears a tripped circuit breaker so the session can resume spending. Circuit breakers trip automatically when limits are exceeded and stay tripped until manually reset.
|
|
223
|
+
|
|
224
|
+
Budget limits can also be set at session creation time via the agent console at mpp32.org/agent-console or by passing `budgetLimitUsd`, `velocityLimitUsd`, and `alertThresholdPercent` to `POST /api/agent/sessions`.
|
|
152
225
|
|
|
153
226
|
## How discovery works
|
|
154
227
|
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { signX402Payment } from "./x402-signers.js";
|
|
6
|
-
const SERVER_VERSION = "1.
|
|
6
|
+
const SERVER_VERSION = "1.4.0";
|
|
7
7
|
// ── Env loading: trim and sanitize aggressively ─────────────────────────────
|
|
8
8
|
// Copy-paste from Claude Desktop / Cursor / Windsurf JSON config UIs frequently
|
|
9
9
|
// adds trailing \n, \r, NBSP, BOM, or wraps the value in literal quotes. Any
|
|
@@ -252,7 +252,7 @@ server.tool("get_mpp32_diagnostics", "Report what the mpp32-mcp-server detected
|
|
|
252
252
|
`- x402 (USDC on Solana) payment: ${SOLANA_PRIVATE_KEY ? "yes" : "no — set MPP32_SOLANA_PRIVATE_KEY"}`,
|
|
253
253
|
`- x402 (USDC on Base/EVM) payment: ${PRIVATE_KEY ? "yes" : "no — set MPP32_PRIVATE_KEY"}`,
|
|
254
254
|
``,
|
|
255
|
-
`**Ready to pay end-to-end:** ${readyToPay ? "YES — try `
|
|
255
|
+
`**Ready to pay end-to-end:** ${readyToPay ? "YES — try `get_solana_token_intelligence` with token=\"M32\" to confirm." : "NO — see the missing items above."}`,
|
|
256
256
|
``,
|
|
257
257
|
`**If a variable shows NOT SET but you set it in claude_desktop_config.json:**`,
|
|
258
258
|
`1. Confirm the file path Claude Desktop actually reads:`,
|
|
@@ -308,6 +308,10 @@ server.tool("list_mpp32_services", "Browse the MPP32 federated catalog of 4,500+
|
|
|
308
308
|
.enum(["native", "x402-bazaar", "mcp-registry", "curated", "free"])
|
|
309
309
|
.optional()
|
|
310
310
|
.describe("Filter by catalog source. 'native' = callable end-to-end; 'curated'/'free' = often callable; 'x402-bazaar'/'mcp-registry' = mostly listing-only."),
|
|
311
|
+
protocol: z
|
|
312
|
+
.enum(["x402", "tempo", "acp", "ap2", "agtp"])
|
|
313
|
+
.optional()
|
|
314
|
+
.describe("Filter by payment protocol (e.g. 'x402' for USDC-settled services)."),
|
|
311
315
|
limit: z
|
|
312
316
|
.number()
|
|
313
317
|
.int()
|
|
@@ -315,7 +319,7 @@ server.tool("list_mpp32_services", "Browse the MPP32 federated catalog of 4,500+
|
|
|
315
319
|
.max(500)
|
|
316
320
|
.optional()
|
|
317
321
|
.describe("Max results (default 100, max 500)."),
|
|
318
|
-
}, async ({ category, q, source, limit }) => {
|
|
322
|
+
}, async ({ category, q, source, protocol, limit }) => {
|
|
319
323
|
try {
|
|
320
324
|
const url = new URL("/api/agent/services", API_URL);
|
|
321
325
|
if (category)
|
|
@@ -324,6 +328,8 @@ server.tool("list_mpp32_services", "Browse the MPP32 federated catalog of 4,500+
|
|
|
324
328
|
url.searchParams.set("q", q);
|
|
325
329
|
if (source)
|
|
326
330
|
url.searchParams.set("source", source);
|
|
331
|
+
if (protocol)
|
|
332
|
+
url.searchParams.set("protocol", protocol);
|
|
327
333
|
url.searchParams.set("limit", String(limit ?? 100));
|
|
328
334
|
const res = await fetchWithTimeout(url.toString(), { headers: buildHeaders() });
|
|
329
335
|
if (!res.ok) {
|
|
@@ -460,6 +466,329 @@ server.tool("get_solana_token_intelligence", "Get real-time Solana token intelli
|
|
|
460
466
|
// Legacy path — direct call to /api/intelligence with manual 402 handling.
|
|
461
467
|
return await legacyIntelligenceCall(token, walletAddress);
|
|
462
468
|
});
|
|
469
|
+
// ── Tool 4: M32-gated Whale Tracker ───────────────────────────────────────
|
|
470
|
+
server.tool("get_m32_whale_tracker", "M32-gated whale analysis for any Solana token. Returns top 20 holders, concentration risk, holder distribution, and buy/sell pressure. Requires the caller to hold 1,000,000+ M32 tokens (balance verified on-chain via X-Wallet-Address header). Free for qualifying holders — no payment required. Returns 403 if the wallet holds insufficient M32.", {
|
|
471
|
+
token: z
|
|
472
|
+
.string()
|
|
473
|
+
.describe("Solana token mint address to analyze for whale activity."),
|
|
474
|
+
walletAddress: z
|
|
475
|
+
.string()
|
|
476
|
+
.describe("Your Solana wallet address. M32 balance is checked on-chain to verify you hold 1M+ M32."),
|
|
477
|
+
}, async ({ token, walletAddress }) => {
|
|
478
|
+
try {
|
|
479
|
+
const res = await fetchWithTimeout(`${API_URL}/api/m32/whale-tracker`, {
|
|
480
|
+
method: "POST",
|
|
481
|
+
headers: buildHeaders({
|
|
482
|
+
"Content-Type": "application/json",
|
|
483
|
+
"X-Wallet-Address": safeHeaderValue("walletAddress", walletAddress),
|
|
484
|
+
}),
|
|
485
|
+
body: JSON.stringify({ token }),
|
|
486
|
+
});
|
|
487
|
+
const text = await res.text();
|
|
488
|
+
let formatted;
|
|
489
|
+
try {
|
|
490
|
+
formatted = JSON.stringify(JSON.parse(text), null, 2);
|
|
491
|
+
}
|
|
492
|
+
catch {
|
|
493
|
+
formatted = text;
|
|
494
|
+
}
|
|
495
|
+
if (res.status === 403) {
|
|
496
|
+
return { content: [{ type: "text", text: `**Access denied.** Whale Tracker requires holding 1,000,000+ M32 tokens. Your wallet does not meet the threshold.\n\nBuy M32: https://raydium.io/swap/?inputMint=sol&outputMint=6hKtz8FV7cAQMrbjcBZeTQAcrYep3WCM83164JpJpump` }] };
|
|
497
|
+
}
|
|
498
|
+
return { content: [{ type: "text", text: `**Whale Tracker** — \`${token}\`\n\n\`\`\`json\n${formatted}\n\`\`\`` }] };
|
|
499
|
+
}
|
|
500
|
+
catch (err) {
|
|
501
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }] };
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
// ── Tool 5: M32-gated Token Comparison ────────────────────────────────────
|
|
505
|
+
server.tool("compare_tokens_m32", "M32-gated head-to-head intelligence comparison of two Solana tokens. Returns side-by-side alpha scores, rug risk, whale activity, volume, liquidity, market data, and a winner verdict. Requires the caller to hold 2,500,000+ M32 tokens (balance verified on-chain via X-Wallet-Address header). Free for qualifying holders. Returns 403 if insufficient M32.", {
|
|
506
|
+
tokenA: z
|
|
507
|
+
.string()
|
|
508
|
+
.describe("First Solana token mint address."),
|
|
509
|
+
tokenB: z
|
|
510
|
+
.string()
|
|
511
|
+
.describe("Second Solana token mint address."),
|
|
512
|
+
walletAddress: z
|
|
513
|
+
.string()
|
|
514
|
+
.describe("Your Solana wallet address. M32 balance is checked on-chain to verify you hold 2.5M+ M32."),
|
|
515
|
+
}, async ({ tokenA, tokenB, walletAddress }) => {
|
|
516
|
+
try {
|
|
517
|
+
const res = await fetchWithTimeout(`${API_URL}/api/m32/compare`, {
|
|
518
|
+
method: "POST",
|
|
519
|
+
headers: buildHeaders({
|
|
520
|
+
"Content-Type": "application/json",
|
|
521
|
+
"X-Wallet-Address": safeHeaderValue("walletAddress", walletAddress),
|
|
522
|
+
}),
|
|
523
|
+
body: JSON.stringify({ tokenA, tokenB }),
|
|
524
|
+
});
|
|
525
|
+
const text = await res.text();
|
|
526
|
+
let formatted;
|
|
527
|
+
try {
|
|
528
|
+
formatted = JSON.stringify(JSON.parse(text), null, 2);
|
|
529
|
+
}
|
|
530
|
+
catch {
|
|
531
|
+
formatted = text;
|
|
532
|
+
}
|
|
533
|
+
if (res.status === 403) {
|
|
534
|
+
return { content: [{ type: "text", text: `**Access denied.** Token Comparison requires holding 2,500,000+ M32 tokens. Your wallet does not meet the threshold.\n\nBuy M32: https://raydium.io/swap/?inputMint=sol&outputMint=6hKtz8FV7cAQMrbjcBZeTQAcrYep3WCM83164JpJpump` }] };
|
|
535
|
+
}
|
|
536
|
+
return { content: [{ type: "text", text: `**Token Comparison** — \`${tokenA}\` vs \`${tokenB}\`\n\n\`\`\`json\n${formatted}\n\`\`\`` }] };
|
|
537
|
+
}
|
|
538
|
+
catch (err) {
|
|
539
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }] };
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
// ── Tool 6: M32-gated Portfolio Scanner ───────────────────────────────────
|
|
543
|
+
server.tool("scan_portfolio_m32", "M32-gated full wallet portfolio scan. Discovers all SPL tokens in a Solana wallet, runs intelligence on top holdings, and returns per-token analysis with aggregate portfolio risk metrics. Requires the caller to hold 5,000,000+ M32 tokens (balance verified on-chain via X-Wallet-Address header). Free for qualifying holders. Returns 403 if insufficient M32.", {
|
|
544
|
+
wallet: z
|
|
545
|
+
.string()
|
|
546
|
+
.describe("Solana wallet address to scan for token holdings."),
|
|
547
|
+
walletAddress: z
|
|
548
|
+
.string()
|
|
549
|
+
.describe("Your Solana wallet address. M32 balance is checked on-chain to verify you hold 5M+ M32."),
|
|
550
|
+
}, async ({ wallet, walletAddress }) => {
|
|
551
|
+
try {
|
|
552
|
+
const res = await fetchWithTimeout(`${API_URL}/api/m32/portfolio`, {
|
|
553
|
+
method: "POST",
|
|
554
|
+
headers: buildHeaders({
|
|
555
|
+
"Content-Type": "application/json",
|
|
556
|
+
"X-Wallet-Address": safeHeaderValue("walletAddress", walletAddress),
|
|
557
|
+
}),
|
|
558
|
+
body: JSON.stringify({ wallet }),
|
|
559
|
+
});
|
|
560
|
+
const text = await res.text();
|
|
561
|
+
let formatted;
|
|
562
|
+
try {
|
|
563
|
+
formatted = JSON.stringify(JSON.parse(text), null, 2);
|
|
564
|
+
}
|
|
565
|
+
catch {
|
|
566
|
+
formatted = text;
|
|
567
|
+
}
|
|
568
|
+
if (res.status === 403) {
|
|
569
|
+
return { content: [{ type: "text", text: `**Access denied.** Portfolio Scanner requires holding 5,000,000+ M32 tokens. Your wallet does not meet the threshold.\n\nBuy M32: https://raydium.io/swap/?inputMint=sol&outputMint=6hKtz8FV7cAQMrbjcBZeTQAcrYep3WCM83164JpJpump` }] };
|
|
570
|
+
}
|
|
571
|
+
return { content: [{ type: "text", text: `**Portfolio Scanner** — wallet \`${wallet}\`\n\n\`\`\`json\n${formatted}\n\`\`\`` }] };
|
|
572
|
+
}
|
|
573
|
+
catch (err) {
|
|
574
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }] };
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
// ── Tool 7: get_pivx_dao_intelligence ─────────────────────────────────────
|
|
578
|
+
server.tool("get_pivx_dao_intelligence", "Get real-time PIVX DAO governance intelligence. Returns active budget proposals with masternode voting tallies (Yes/No/Abstain percentages), budget allocation status, network deflation metrics (unallocated treasury PIV that are never minted), and masternode network health. PIVX is a fully community-governed cryptocurrency where Masternode owners vote on budget proposals every ~30 days. Data sourced from pivx.org/proposals and the PIVX blockchain. Free — no payment required.", {
|
|
579
|
+
filter: z
|
|
580
|
+
.enum(["all", "passing", "failing"])
|
|
581
|
+
.default("all")
|
|
582
|
+
.optional()
|
|
583
|
+
.describe("Filter proposals by status: 'all' (default), 'passing' (funded proposals), or 'failing' (below threshold)."),
|
|
584
|
+
includeStats: z
|
|
585
|
+
.boolean()
|
|
586
|
+
.default(true)
|
|
587
|
+
.optional()
|
|
588
|
+
.describe("Include network stats and deflation metrics (default: true)."),
|
|
589
|
+
}, async ({ filter, includeStats }) => {
|
|
590
|
+
try {
|
|
591
|
+
const statusFilter = filter === "passing" || filter === "failing" ? `?status=${filter}` : "";
|
|
592
|
+
const endpoint = includeStats !== false ? "/api/governance" : `/api/governance/proposals${statusFilter}`;
|
|
593
|
+
const res = await fetchWithTimeout(`${API_URL}${endpoint}`, {
|
|
594
|
+
headers: buildHeaders(),
|
|
595
|
+
});
|
|
596
|
+
if (!res.ok) {
|
|
597
|
+
const err = await res.json().catch(() => null);
|
|
598
|
+
return {
|
|
599
|
+
content: [{
|
|
600
|
+
type: "text",
|
|
601
|
+
text: `Error fetching PIVX governance data: ${err?.error?.message ?? `HTTP ${res.status}`}`,
|
|
602
|
+
}],
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
const json = await res.json();
|
|
606
|
+
const data = json.data;
|
|
607
|
+
// Build readable output
|
|
608
|
+
const lines = [];
|
|
609
|
+
lines.push("# PIVX DAO Governance Intelligence");
|
|
610
|
+
lines.push("");
|
|
611
|
+
// Network stats
|
|
612
|
+
const network = data.network;
|
|
613
|
+
if (network) {
|
|
614
|
+
lines.push("## Network Overview");
|
|
615
|
+
lines.push(`- **Masternodes Online:** ${network.masternodeCount}`);
|
|
616
|
+
lines.push(`- **Passing Threshold:** ${network.passingThreshold} votes (10% of masternodes)`);
|
|
617
|
+
lines.push(`- **Monthly Budget:** ${Number(network.monthlyBudgetPiv).toLocaleString()} PIV (~$${Number(network.monthlyBudgetUsd).toLocaleString()})`);
|
|
618
|
+
lines.push(`- **Budget Allocated:** ${Number(network.budgetAllocatedPiv).toLocaleString()} PIV (${network.budgetAllocatedPercent}%)`);
|
|
619
|
+
if (network.blockHeight)
|
|
620
|
+
lines.push(`- **Block Height:** ${Number(network.blockHeight).toLocaleString()}`);
|
|
621
|
+
if (network.totalSupply)
|
|
622
|
+
lines.push(`- **Total Supply:** ${Math.round(Number(network.totalSupply)).toLocaleString()} PIV`);
|
|
623
|
+
lines.push("");
|
|
624
|
+
}
|
|
625
|
+
// Deflation stats
|
|
626
|
+
const deflation = data.deflation;
|
|
627
|
+
if (deflation) {
|
|
628
|
+
lines.push("## Deflation / Fee Burn Metrics");
|
|
629
|
+
lines.push(`- **Unallocated PIV This Cycle:** ${Number(deflation.unallocatedPivPerCycle).toLocaleString()} PIV (never minted)`);
|
|
630
|
+
lines.push(`- **Annual Unallocated (est.):** ${Number(deflation.annualUnallocatedPiv).toLocaleString()} PIV`);
|
|
631
|
+
lines.push(`- **Effective Inflation Reduction:** ${deflation.effectiveInflationReduction}`);
|
|
632
|
+
lines.push(`- **Proposal Submission Fee:** ${deflation.proposalFeeBurnPiv} PIV (burned/destroyed)`);
|
|
633
|
+
lines.push("");
|
|
634
|
+
}
|
|
635
|
+
// Proposals
|
|
636
|
+
let proposals = (data.proposals ?? []);
|
|
637
|
+
if (filter === "passing")
|
|
638
|
+
proposals = proposals.filter((p) => p.status === "passing");
|
|
639
|
+
else if (filter === "failing")
|
|
640
|
+
proposals = proposals.filter((p) => p.status === "failing");
|
|
641
|
+
if (proposals.length > 0) {
|
|
642
|
+
lines.push(`## Active Proposals (${proposals.length})`);
|
|
643
|
+
lines.push("");
|
|
644
|
+
for (const p of proposals) {
|
|
645
|
+
const status = p.status === "passing" ? "PASSING" : "FAILING";
|
|
646
|
+
const fundedTag = p.funded ? " (Funded)" : "";
|
|
647
|
+
lines.push(`### ${p.name} — ${status}${fundedTag}`);
|
|
648
|
+
lines.push(`- **Votes:** ${p.yesVotes} Yes / ${p.noVotes} No (${p.netYesPercent}% net yes)`);
|
|
649
|
+
lines.push(`- **Monthly Payment:** ${Number(p.monthlyPaymentPiv).toLocaleString()} PIV (~$${Number(p.monthlyPaymentUsd).toLocaleString()})`);
|
|
650
|
+
if (Number(p.totalPaymentPiv) > Number(p.monthlyPaymentPiv)) {
|
|
651
|
+
lines.push(`- **Total Budget:** ${Number(p.totalPaymentPiv).toLocaleString()} PIV`);
|
|
652
|
+
}
|
|
653
|
+
if (Number(p.installmentsRemaining) > 0) {
|
|
654
|
+
lines.push(`- **Installments Remaining:** ${p.installmentsRemaining}`);
|
|
655
|
+
}
|
|
656
|
+
if (p.budgetPercent)
|
|
657
|
+
lines.push(`- **Budget Usage:** ${p.budgetPercent}%`);
|
|
658
|
+
if (p.url)
|
|
659
|
+
lines.push(`- **Details:** ${p.url}`);
|
|
660
|
+
lines.push("");
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
lines.push("No proposals found matching the filter.");
|
|
665
|
+
}
|
|
666
|
+
// Meta
|
|
667
|
+
const meta = data.meta;
|
|
668
|
+
if (meta) {
|
|
669
|
+
lines.push("---");
|
|
670
|
+
lines.push(`Source: ${meta.source} | ${meta.timestamp}${meta.cacheHit ? " (cached)" : ""}`);
|
|
671
|
+
}
|
|
672
|
+
return {
|
|
673
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
catch (err) {
|
|
677
|
+
return {
|
|
678
|
+
content: [{
|
|
679
|
+
type: "text",
|
|
680
|
+
text: `Failed to fetch PIVX governance data: ${err instanceof Error ? err.message : String(err)}`,
|
|
681
|
+
}],
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
// ── Tool 8: manage_agent_budget ────────────────────────────────────────────
|
|
686
|
+
server.tool("manage_agent_budget", "View, set, or reset the spending circuit breaker for your MPP32 agent session. Use 'get' to check current budget status (remaining budget, hourly velocity, circuit breaker state). Use 'set' to configure spending limits (budget cap in USD, hourly velocity limit, alert threshold percentage). Use 'reset' to manually reset a tripped circuit breaker so the session can resume spending. Circuit breakers trip automatically when budget or velocity limits are exceeded, preventing runaway agent spending.", {
|
|
687
|
+
action: z.enum(["get", "set", "reset"]).describe("Action: 'get' = view budget status, 'set' = update limits, 'reset' = clear tripped circuit breaker"),
|
|
688
|
+
budgetLimitUsd: z.number().positive().max(1_000_000).optional().describe("Maximum total session spend in USD. Only used with action='set'."),
|
|
689
|
+
velocityLimitUsd: z.number().positive().max(1_000_000).optional().describe("Maximum spend per hour in USD. Only used with action='set'."),
|
|
690
|
+
alertThresholdPercent: z.number().int().min(1).max(100).optional().describe("Budget percentage at which to warn (e.g. 80 = warn at 80% spent). Only used with action='set'."),
|
|
691
|
+
}, async ({ action, budgetLimitUsd, velocityLimitUsd, alertThresholdPercent }) => {
|
|
692
|
+
if (!AGENT_KEY) {
|
|
693
|
+
return {
|
|
694
|
+
content: [{ type: "text", text: "**MPP32_AGENT_KEY not configured.** Set it in your MCP config to manage budgets." }],
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
try {
|
|
698
|
+
if (action === "get") {
|
|
699
|
+
const res = await fetchWithTimeout(new URL("/api/agent/spending", API_URL).toString(), { headers: buildHeaders() });
|
|
700
|
+
if (!res.ok) {
|
|
701
|
+
const err = await res.json().catch(() => null);
|
|
702
|
+
return { content: [{ type: "text", text: `Error fetching budget: ${err?.error?.message ?? res.statusText}` }] };
|
|
703
|
+
}
|
|
704
|
+
const data = (await res.json()).data;
|
|
705
|
+
const lines = [
|
|
706
|
+
`**MPP32 Session Budget Status**`,
|
|
707
|
+
``,
|
|
708
|
+
];
|
|
709
|
+
if (data.budgetLimitUsd != null) {
|
|
710
|
+
lines.push(`Budget: $${data.totalSpentUsd.toFixed(4)} spent of $${data.budgetLimitUsd.toFixed(4)} ($${data.remainingBudgetUsd.toFixed(4)} remaining, ${data.budgetUtilizationPercent}% used)`);
|
|
711
|
+
}
|
|
712
|
+
else {
|
|
713
|
+
lines.push(`Budget: unlimited (no cap set)`);
|
|
714
|
+
lines.push(`Total spent: $${data.totalSpentUsd.toFixed(4)} across ${data.totalSettledCalls} settled calls`);
|
|
715
|
+
}
|
|
716
|
+
if (data.velocityLimitUsd != null) {
|
|
717
|
+
lines.push(`Velocity: $${data.hourlySpendUsd.toFixed(4)}/hr of $${data.velocityLimitUsd.toFixed(4)}/hr limit (${data.hourlySettledCalls} calls this hour)`);
|
|
718
|
+
}
|
|
719
|
+
if (data.circuitBreakerTripped) {
|
|
720
|
+
lines.push(``);
|
|
721
|
+
lines.push(`**CIRCUIT BREAKER TRIPPED** — ${data.circuitBreakerReason}`);
|
|
722
|
+
lines.push(`Tripped at: ${data.circuitBreakerTrippedAt}`);
|
|
723
|
+
lines.push(`Use action="reset" to resume spending.`);
|
|
724
|
+
}
|
|
725
|
+
if (data.byService?.length) {
|
|
726
|
+
lines.push(``);
|
|
727
|
+
lines.push(`**Spending by service:**`);
|
|
728
|
+
for (const s of data.byService) {
|
|
729
|
+
lines.push(`- ${s.service}: $${s.totalSpentUsd.toFixed(4)} (${s.count} calls)`);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
733
|
+
}
|
|
734
|
+
if (action === "set") {
|
|
735
|
+
const payload = {};
|
|
736
|
+
if (budgetLimitUsd !== undefined)
|
|
737
|
+
payload.budgetLimitUsd = budgetLimitUsd;
|
|
738
|
+
if (velocityLimitUsd !== undefined)
|
|
739
|
+
payload.velocityLimitUsd = velocityLimitUsd;
|
|
740
|
+
if (alertThresholdPercent !== undefined)
|
|
741
|
+
payload.alertThresholdPercent = alertThresholdPercent;
|
|
742
|
+
if (Object.keys(payload).length === 0) {
|
|
743
|
+
return { content: [{ type: "text", text: "Provide at least one of: budgetLimitUsd, velocityLimitUsd, alertThresholdPercent." }] };
|
|
744
|
+
}
|
|
745
|
+
const res = await fetchWithTimeout(new URL("/api/agent/budget", API_URL).toString(), {
|
|
746
|
+
method: "PATCH",
|
|
747
|
+
headers: buildHeaders({ "Content-Type": "application/json" }),
|
|
748
|
+
body: JSON.stringify(payload),
|
|
749
|
+
});
|
|
750
|
+
if (!res.ok) {
|
|
751
|
+
const err = await res.json().catch(() => null);
|
|
752
|
+
return { content: [{ type: "text", text: `Error updating budget: ${err?.error?.message ?? res.statusText}` }] };
|
|
753
|
+
}
|
|
754
|
+
const data = (await res.json()).data;
|
|
755
|
+
const lines = [
|
|
756
|
+
`**Budget updated successfully.**`,
|
|
757
|
+
``,
|
|
758
|
+
data.budgetLimitUsd != null ? `Budget limit: $${data.budgetLimitUsd.toFixed(4)}` : `Budget limit: unlimited`,
|
|
759
|
+
data.velocityLimitUsd != null ? `Velocity limit: $${data.velocityLimitUsd.toFixed(4)}/hr` : `Velocity limit: unlimited`,
|
|
760
|
+
`Total spent: $${data.totalSpentUsd.toFixed(4)}`,
|
|
761
|
+
data.remainingBudgetUsd != null ? `Remaining: $${data.remainingBudgetUsd.toFixed(4)}` : ``,
|
|
762
|
+
data.circuitBreakerTripped ? `\n**Note:** Circuit breaker is still tripped. Use action="reset" to resume.` : ``,
|
|
763
|
+
].filter(Boolean);
|
|
764
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
765
|
+
}
|
|
766
|
+
if (action === "reset") {
|
|
767
|
+
const res = await fetchWithTimeout(new URL("/api/agent/circuit-breaker/reset", API_URL).toString(), {
|
|
768
|
+
method: "POST",
|
|
769
|
+
headers: buildHeaders({ "Content-Type": "application/json" }),
|
|
770
|
+
});
|
|
771
|
+
if (!res.ok) {
|
|
772
|
+
const err = await res.json().catch(() => null);
|
|
773
|
+
return { content: [{ type: "text", text: `Error resetting circuit breaker: ${err?.error?.message ?? res.statusText}` }] };
|
|
774
|
+
}
|
|
775
|
+
const data = (await res.json()).data;
|
|
776
|
+
const lines = [
|
|
777
|
+
data.previousReason
|
|
778
|
+
? `**Circuit breaker reset.** Previous reason: ${data.previousReason}.`
|
|
779
|
+
: `**Circuit breaker was not tripped.** No action needed.`,
|
|
780
|
+
``,
|
|
781
|
+
data.budgetLimitUsd != null ? `Budget: $${data.totalSpentUsd.toFixed(4)} / $${data.budgetLimitUsd.toFixed(4)} ($${data.remainingBudgetUsd.toFixed(4)} remaining)` : ``,
|
|
782
|
+
`Session can resume spending.`,
|
|
783
|
+
].filter(Boolean);
|
|
784
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
785
|
+
}
|
|
786
|
+
return { content: [{ type: "text", text: "Unknown action. Use 'get', 'set', or 'reset'." }] };
|
|
787
|
+
}
|
|
788
|
+
catch (err) {
|
|
789
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }] };
|
|
790
|
+
}
|
|
791
|
+
});
|
|
463
792
|
// ── Core: agent/execute path with 402 sign-and-retry ────────────────────────
|
|
464
793
|
async function callViaAgentExecute(service, method, body, query, path) {
|
|
465
794
|
try {
|
|
@@ -637,6 +966,10 @@ function formatExecuteSuccess(resp, protoOverride) {
|
|
|
637
966
|
else if (meta?.paymentMethod === "unsettled") {
|
|
638
967
|
lines.push(`Service responded but no payment was verified. This should not happen for paid services.`);
|
|
639
968
|
}
|
|
969
|
+
if (meta?.budget && meta.budget.budgetLimitUsd != null) {
|
|
970
|
+
const b = meta.budget;
|
|
971
|
+
lines.push(`Budget: $${b.remainingBudgetUsd.toFixed(4)} remaining (${b.budgetUtilizationPercent}% of $${b.budgetLimitUsd.toFixed(4)} used)`);
|
|
972
|
+
}
|
|
640
973
|
lines.push("");
|
|
641
974
|
lines.push("```json");
|
|
642
975
|
lines.push(formatted);
|
|
@@ -645,6 +978,25 @@ function formatExecuteSuccess(resp, protoOverride) {
|
|
|
645
978
|
}
|
|
646
979
|
function formatExecuteHardError(status, body) {
|
|
647
980
|
const code = body?.error?.code;
|
|
981
|
+
if (code === "MPP32_CIRCUIT_BREAKER_TRIPPED" || (status === 429 && body?.error?.budgetStatus)) {
|
|
982
|
+
const bs = body?.error?.budgetStatus;
|
|
983
|
+
return {
|
|
984
|
+
content: [
|
|
985
|
+
{
|
|
986
|
+
type: "text",
|
|
987
|
+
text: [
|
|
988
|
+
`**Circuit breaker tripped** — spending limit reached.`,
|
|
989
|
+
``,
|
|
990
|
+
body?.error?.message ?? "Session budget exhausted.",
|
|
991
|
+
bs?.budgetLimitUsd != null ? `Budget: $${bs.totalSpentUsd?.toFixed(4) ?? "?"} / $${bs.budgetLimitUsd.toFixed(4)}` : "",
|
|
992
|
+
bs?.velocityLimitUsd != null ? `Velocity: $${bs.hourlySpendUsd?.toFixed(4) ?? "?"}/hr of $${bs.velocityLimitUsd.toFixed(4)}/hr limit` : "",
|
|
993
|
+
``,
|
|
994
|
+
`To resume: use \`manage_agent_budget\` with action="reset", or increase the budget with action="set".`,
|
|
995
|
+
].filter(Boolean).join("\n"),
|
|
996
|
+
},
|
|
997
|
+
],
|
|
998
|
+
};
|
|
999
|
+
}
|
|
648
1000
|
if (code === "NOT_HTTP_CALLABLE") {
|
|
649
1001
|
return {
|
|
650
1002
|
content: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mpp32-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"mcpName": "io.github.MPP32/mpp32-mcp-server",
|
|
5
5
|
"description": "Payment layer for AI agents. One MCP, five protocols, thousands of paid APIs your agent can call.",
|
|
6
6
|
"type": "module",
|
|
@@ -52,7 +52,10 @@
|
|
|
52
52
|
"crypto",
|
|
53
53
|
"defi",
|
|
54
54
|
"token-intelligence",
|
|
55
|
-
"api-marketplace"
|
|
55
|
+
"api-marketplace",
|
|
56
|
+
"pivx",
|
|
57
|
+
"governance",
|
|
58
|
+
"dao"
|
|
56
59
|
],
|
|
57
60
|
"license": "MIT",
|
|
58
61
|
"author": "MPP32 <admin@mpp32.org> (https://mpp32.org)",
|