pion-mcp 0.4.1 → 0.4.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 +4 -2
- package/dist/index.js +46 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
**Model Context Protocol server for Pi Network** — connect AI agents
|
|
4
4
|
(Claude, Cursor, and any MCP-compatible client) to Pi Network chain data.
|
|
5
5
|
|
|
6
|
+
[](https://glama.ai/mcp/servers/jleeblack/pion-mcp)
|
|
7
|
+
|
|
6
8
|
> ⚠️ **Reads: both networks. Payments: testnet only.** The chain tools query Pi
|
|
7
9
|
> Mainnet or Pi Testnet, selected with `PION_NETWORK`. `send_payment` moves real
|
|
8
10
|
> funds, must be explicitly armed, and *cannot* be armed on mainnet — Pi
|
|
@@ -130,8 +132,8 @@ claude mcp add pion -- node /absolute/path/to/pion-mcp/dist/index.js
|
|
|
130
132
|
|
|
131
133
|
| Variable | Default | Purpose |
|
|
132
134
|
|---|---|---|
|
|
133
|
-
| `PION_NETWORK` | `testnet` | Which chain the read tools query — `testnet` or `mainnet
|
|
134
|
-
| `PION_HORIZON_URL` | derived from `PION_NETWORK` | Horizon base URL
|
|
135
|
+
| `PION_NETWORK` | `testnet` | Which chain the read tools query — `testnet` or `mainnet`. Mainnet is echoed as **REAL VALUE** in the startup banner |
|
|
136
|
+
| `PION_HORIZON_URL` | derived from `PION_NETWORK` | Override for the Horizon base URL. Optional. If set alongside `PION_NETWORK` the two must name the same chain — a contradiction is a startup error, not a silent winner |
|
|
135
137
|
| `PION_PLATFORM_URL` | `https://api.minepi.com` | Platform API base URL |
|
|
136
138
|
| `PION_ENABLE_PAYMENTS` | unset (off) | Arms `send_payment` — see Tier C above |
|
|
137
139
|
| `PION_MAX_PAYMENT_PI` | unset | Required per-payment ceiling when armed |
|
package/dist/index.js
CHANGED
|
@@ -50,8 +50,11 @@ if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
|
50
50
|
" send_payment (only when explicitly armed — see below)",
|
|
51
51
|
"",
|
|
52
52
|
"Environment:",
|
|
53
|
-
" PION_NETWORK testnet (default) or mainnet — which chain the read tools
|
|
54
|
-
"
|
|
53
|
+
" PION_NETWORK testnet (default) or mainnet — which chain the read tools",
|
|
54
|
+
" query. mainnet is echoed as REAL VALUE in the startup banner.",
|
|
55
|
+
" PION_HORIZON_URL Override for the Horizon base URL. Optional; derived from",
|
|
56
|
+
" PION_NETWORK when unset. If both are set they must name the",
|
|
57
|
+
" same chain — a contradiction is a startup error, not a guess.",
|
|
55
58
|
" PION_PLATFORM_URL Platform API base URL (default: https://api.minepi.com)",
|
|
56
59
|
"",
|
|
57
60
|
"Reads work on both Pi chains. Payments do not: Pi restricts App-to-User",
|
|
@@ -72,29 +75,54 @@ if (NETWORK_ERROR) {
|
|
|
72
75
|
console.error(`pion-mcp: ${NETWORK_ERROR.message}`);
|
|
73
76
|
process.exit(1);
|
|
74
77
|
}
|
|
75
|
-
const server = new McpServer({ name: "pion-mcp", version: VERSION }, {
|
|
76
|
-
instructions: `Pion exposes read-only Pi Network data. get_wallet_balance, get_account_payments, ` +
|
|
77
|
-
`and query_transaction are public ledger reads from Horizon at ${HORIZON_URL} ` +
|
|
78
|
-
`(${NETWORK.label}), needing no credentials. This server is reading ` +
|
|
79
|
-
`${NETWORK.label} — every result repeats it in its "network" field, and the two Pi ` +
|
|
80
|
-
`chains are separate ledgers, so an address funded on one does not exist on the ` +
|
|
81
|
-
`other. Amounts are decimal strings; Pi itself is ` +
|
|
82
|
-
'reported as the asset "PI", custom tokens as "CODE:ISSUER", and liquidity-pool ' +
|
|
83
|
-
'shares as "pool:ID". verify_user is different: it checks a user access token ' +
|
|
84
|
-
`against the Pi Platform API at ${PLATFORM_URL} and requires the caller to supply ` +
|
|
85
|
-
"that token. No tool here can send payments, sign anything, or spend from a wallet.",
|
|
86
|
-
});
|
|
87
|
-
registerGetWalletBalance(server, NETWORK);
|
|
88
|
-
registerGetAccountPayments(server, NETWORK);
|
|
89
|
-
registerQueryTransaction(server, NETWORK);
|
|
90
|
-
registerVerifyUser(server);
|
|
91
78
|
// Tier C is registered only when fully armed. A disarmed server does not
|
|
92
79
|
// advertise a payment tool at all, so an agent cannot try to spend and cannot
|
|
93
80
|
// be talked into thinking it might succeed.
|
|
94
81
|
//
|
|
95
82
|
// Passed the resolved network, not the URL: arming turns on what chain this
|
|
96
83
|
// *is*, and a string containing "testnet" is not the same claim.
|
|
84
|
+
//
|
|
85
|
+
// Resolved BEFORE the server is constructed because the instructions below
|
|
86
|
+
// state whether a spend tool exists, and that claim has to be built from the
|
|
87
|
+
// same answer that decides whether one is registered. Until 0.4.2 the check
|
|
88
|
+
// ran afterwards and the instructions said "no tool here can send payments"
|
|
89
|
+
// unconditionally — false on an armed server, which is the one configuration
|
|
90
|
+
// where being wrong about it costs money.
|
|
97
91
|
const payments = checkPaymentsArming(NETWORK);
|
|
92
|
+
/**
|
|
93
|
+
* Server instructions — the text a client places ahead of the tool catalog.
|
|
94
|
+
*
|
|
95
|
+
* Every session pays for this in context, so it carries only what changes a
|
|
96
|
+
* decision an agent is about to make, and nothing recoverable from a tool
|
|
97
|
+
* description it will read anyway.
|
|
98
|
+
*
|
|
99
|
+
* The cross-chain sentence is the reason this exists. It previously said an
|
|
100
|
+
* address funded on one chain "does not exist on the other" — measured false
|
|
101
|
+
* on 2026-08-14 (docs/FINDINGS.md finding 5): one address held 2.06 Pi on
|
|
102
|
+
* mainnet and 32.29938 Pi on testnet simultaneously. That wording invited
|
|
103
|
+
* exactly the wrong inference, that a wrong-chain read fails loudly. It does
|
|
104
|
+
* not; it returns a plausible number. An agent needs the true version before
|
|
105
|
+
* it reports a figure, not after.
|
|
106
|
+
*/
|
|
107
|
+
const instructions = `Pion reads Pi Network chain data. get_wallet_balance, get_account_payments and ` +
|
|
108
|
+
`query_transaction are public Horizon reads at ${HORIZON_URL}, needing no ` +
|
|
109
|
+
`credentials. verify_user checks a caller-supplied user access token against the ` +
|
|
110
|
+
`Pi Platform API at ${PLATFORM_URL}. ` +
|
|
111
|
+
`This server reads ${NETWORK.label}, and every result carries a "network" field — ` +
|
|
112
|
+
`check it before trusting a figure. The two Pi chains are separate ledgers sharing ` +
|
|
113
|
+
`one address format, and the same address can hold different balances on each: a ` +
|
|
114
|
+
`wrong-chain read returns a plausible wrong number, not an error. Testnet Pi has no ` +
|
|
115
|
+
`monetary value. Amounts are decimal strings; Pi is "PI", tokens "CODE:ISSUER", ` +
|
|
116
|
+
`pool shares "pool:ID". ` +
|
|
117
|
+
(payments.armed
|
|
118
|
+
? `send_payment is ARMED and can spend up to ${payments.config.maxAmountPi} Pi per ` +
|
|
119
|
+
`call from the app wallet on ${NETWORK.label}; every other tool is read-only.`
|
|
120
|
+
: "No tool here can send payments, sign anything, or spend from a wallet.");
|
|
121
|
+
const server = new McpServer({ name: "pion-mcp", version: VERSION }, { instructions });
|
|
122
|
+
registerGetWalletBalance(server, NETWORK);
|
|
123
|
+
registerGetAccountPayments(server, NETWORK);
|
|
124
|
+
registerQueryTransaction(server, NETWORK);
|
|
125
|
+
registerVerifyUser(server);
|
|
98
126
|
if (payments.armed) {
|
|
99
127
|
registerSendPayment(server, payments.config);
|
|
100
128
|
}
|
package/package.json
CHANGED