@pincerpay/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 +131 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +30 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +28 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +60 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/debug-transaction.d.ts +3 -0
- package/dist/prompts/debug-transaction.d.ts.map +1 -0
- package/dist/prompts/debug-transaction.js +31 -0
- package/dist/prompts/debug-transaction.js.map +1 -0
- package/dist/prompts/get-started.d.ts +3 -0
- package/dist/prompts/get-started.d.ts.map +1 -0
- package/dist/prompts/get-started.js +40 -0
- package/dist/prompts/get-started.js.map +1 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +11 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/integrate-agent.d.ts +3 -0
- package/dist/prompts/integrate-agent.d.ts.map +1 -0
- package/dist/prompts/integrate-agent.js +41 -0
- package/dist/prompts/integrate-agent.js.map +1 -0
- package/dist/prompts/integrate-merchant.d.ts +3 -0
- package/dist/prompts/integrate-merchant.d.ts.map +1 -0
- package/dist/prompts/integrate-merchant.js +39 -0
- package/dist/prompts/integrate-merchant.js.map +1 -0
- package/dist/resources/chain-config.d.ts +3 -0
- package/dist/resources/chain-config.d.ts.map +1 -0
- package/dist/resources/chain-config.js +29 -0
- package/dist/resources/chain-config.js.map +1 -0
- package/dist/resources/docs.d.ts +3 -0
- package/dist/resources/docs.d.ts.map +1 -0
- package/dist/resources/docs.js +460 -0
- package/dist/resources/docs.js.map +1 -0
- package/dist/resources/index.d.ts +4 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +9 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/openapi-spec.d.ts +4 -0
- package/dist/resources/openapi-spec.d.ts.map +1 -0
- package/dist/resources/openapi-spec.js +28 -0
- package/dist/resources/openapi-spec.js.map +1 -0
- package/dist/server.d.ts +18 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +48 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/check-transaction.d.ts +4 -0
- package/dist/tools/check-transaction.d.ts.map +1 -0
- package/dist/tools/check-transaction.js +50 -0
- package/dist/tools/check-transaction.js.map +1 -0
- package/dist/tools/estimate-gas.d.ts +3 -0
- package/dist/tools/estimate-gas.d.ts.map +1 -0
- package/dist/tools/estimate-gas.js +88 -0
- package/dist/tools/estimate-gas.js.map +1 -0
- package/dist/tools/generate-ucp.d.ts +3 -0
- package/dist/tools/generate-ucp.d.ts.map +1 -0
- package/dist/tools/generate-ucp.js +103 -0
- package/dist/tools/generate-ucp.js.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +19 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-chains.d.ts +4 -0
- package/dist/tools/list-chains.d.ts.map +1 -0
- package/dist/tools/list-chains.js +56 -0
- package/dist/tools/list-chains.js.map +1 -0
- package/dist/tools/scaffold-agent.d.ts +3 -0
- package/dist/tools/scaffold-agent.d.ts.map +1 -0
- package/dist/tools/scaffold-agent.js +93 -0
- package/dist/tools/scaffold-agent.js.map +1 -0
- package/dist/tools/scaffold-middleware.d.ts +3 -0
- package/dist/tools/scaffold-middleware.d.ts.map +1 -0
- package/dist/tools/scaffold-middleware.js +160 -0
- package/dist/tools/scaffold-middleware.js.map +1 -0
- package/dist/tools/validate-config.d.ts +3 -0
- package/dist/tools/validate-config.d.ts.map +1 -0
- package/dist/tools/validate-config.js +105 -0
- package/dist/tools/validate-config.js.map +1 -0
- package/dist/transport/http.d.ts +7 -0
- package/dist/transport/http.d.ts.map +1 -0
- package/dist/transport/http.js +34 -0
- package/dist/transport/http.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
const DOCS = {
|
|
3
|
+
"getting-started": {
|
|
4
|
+
title: "Getting Started with PincerPay",
|
|
5
|
+
content: `# Getting Started with PincerPay
|
|
6
|
+
|
|
7
|
+
PincerPay is an on-chain USDC payment gateway for AI agents using the x402 protocol (HTTP 402).
|
|
8
|
+
No card rails — pure stablecoin settlement on Solana (primary), Base, and Polygon.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- Node.js 22+
|
|
13
|
+
- \`"type": "module"\` in your package.json — both SDKs are **ESM-only**. Without this, you'll get \`ERR_MODULE_NOT_FOUND\`.
|
|
14
|
+
- A USDC wallet (Solana or EVM) for receiving/sending payments
|
|
15
|
+
|
|
16
|
+
## Choose Your Path
|
|
17
|
+
|
|
18
|
+
### Merchant — Accept USDC payments from AI agents
|
|
19
|
+
You have an API and want to add payment walls so agents pay per request.
|
|
20
|
+
|
|
21
|
+
1. **Install**: \`npm install @pincerpay/merchant\`
|
|
22
|
+
2. **Get an API key**: Sign up at https://pincerpay.com/dashboard → Settings → API Keys (\`pp_live_...\`)
|
|
23
|
+
3. **Generate code**: Use the \`scaffold-x402-middleware\` tool (supports Express, Hono, Next.js)
|
|
24
|
+
4. **Validate config**: Use the \`validate-payment-config\` tool to check your setup
|
|
25
|
+
5. **Add discovery**: Use the \`generate-ucp-manifest\` tool for agent discoverability
|
|
26
|
+
|
|
27
|
+
→ Full guide: \`docs://pincerpay/merchant\`
|
|
28
|
+
|
|
29
|
+
### Agent Developer — Build agents that pay for API access
|
|
30
|
+
You're building an AI agent that needs to automatically pay for paywalled APIs.
|
|
31
|
+
|
|
32
|
+
1. **Install**: \`npm install @pincerpay/agent\`
|
|
33
|
+
2. **Generate code**: Use the \`scaffold-agent-client\` tool with your chain and spending limits
|
|
34
|
+
3. **Estimate costs**: Use the \`estimate-gas-cost\` tool to understand fees on your chain
|
|
35
|
+
|
|
36
|
+
→ Full guide: \`docs://pincerpay/agent\`
|
|
37
|
+
|
|
38
|
+
### Already Integrated? Troubleshooting
|
|
39
|
+
Use the \`debug-transaction\` prompt with your transaction hash, or see \`docs://pincerpay/troubleshooting\`.
|
|
40
|
+
|
|
41
|
+
## Security Checklist
|
|
42
|
+
- Add \`.env*\` to \`.gitignore\` — **never commit API keys or private keys**
|
|
43
|
+
- Store wallet keys in environment variables, not source code
|
|
44
|
+
- Use \`pp_test_\` keys and devnet chains during development
|
|
45
|
+
|
|
46
|
+
## Devnet vs Mainnet
|
|
47
|
+
|
|
48
|
+
| Environment | Chain Shorthand | Notes |
|
|
49
|
+
|-------------|----------------|-------|
|
|
50
|
+
| Development | \`"solana-devnet"\` | Free devnet USDC. Use Solana faucet for SOL. |
|
|
51
|
+
| Development | \`"base-sepolia"\` | Free testnet USDC via Circle faucet. |
|
|
52
|
+
| Production | \`"solana"\` | Real USDC on Solana mainnet. |
|
|
53
|
+
| Production | \`"base"\` | Real USDC on Base mainnet. |
|
|
54
|
+
|
|
55
|
+
**Both merchant and agent must use the same chain** (e.g., both on \`"solana-devnet"\`).
|
|
56
|
+
|
|
57
|
+
## How It Works
|
|
58
|
+
|
|
59
|
+
1. Merchant wraps API routes with PincerPay middleware
|
|
60
|
+
2. Agent calls the API and receives HTTP 402 with payment challenge
|
|
61
|
+
3. Agent SDK automatically signs a USDC transfer
|
|
62
|
+
4. PincerPay facilitator verifies the signature and broadcasts the transaction
|
|
63
|
+
5. Merchant delivers the protected resource
|
|
64
|
+
|
|
65
|
+
## Supported Chains
|
|
66
|
+
- **Solana** (primary) — ~$0.00025 gas, 400ms block time
|
|
67
|
+
- **Base** (EVM) — ~$0.001-0.01 gas, 2s block time
|
|
68
|
+
- **Polygon** (EVM) — ~$0.001-0.005 gas, 2s block time
|
|
69
|
+
|
|
70
|
+
## Key Concepts
|
|
71
|
+
- **Optimistic Finality**: Payments under $1 USDC are released after mempool broadcast (~200ms)
|
|
72
|
+
- **Gas Passthrough**: Agents pay gas costs in USDC (via Kora on Solana, meta-txns on EVM), not merchants
|
|
73
|
+
- **x402 Protocol**: HTTP 402-based payment challenges (Coinbase open standard)
|
|
74
|
+
- **Prices vs Policies**: Route \`price\` uses human-readable amounts ("0.01"), spending \`policies\` use base units ("10000")`,
|
|
75
|
+
},
|
|
76
|
+
merchant: {
|
|
77
|
+
title: "Merchant Integration Guide",
|
|
78
|
+
content: `# Merchant SDK Integration
|
|
79
|
+
|
|
80
|
+
## Install
|
|
81
|
+
|
|
82
|
+
\`\`\`bash
|
|
83
|
+
npm install @pincerpay/merchant
|
|
84
|
+
\`\`\`
|
|
85
|
+
|
|
86
|
+
Sub-path imports are available for tree-shaking: \`@pincerpay/merchant/express\` and \`@pincerpay/merchant/hono\`.
|
|
87
|
+
|
|
88
|
+
## Express Middleware
|
|
89
|
+
|
|
90
|
+
\`\`\`typescript
|
|
91
|
+
import express from "express";
|
|
92
|
+
import { pincerpay } from "@pincerpay/merchant/express";
|
|
93
|
+
|
|
94
|
+
const app = express();
|
|
95
|
+
|
|
96
|
+
app.use(
|
|
97
|
+
pincerpay({
|
|
98
|
+
apiKey: process.env.PINCERPAY_API_KEY!,
|
|
99
|
+
merchantAddress: "YOUR_SOLANA_WALLET_ADDRESS",
|
|
100
|
+
routes: {
|
|
101
|
+
"GET /api/weather": { price: "0.001", chain: "solana" },
|
|
102
|
+
"GET /api/premium": { price: "0.01", chain: "solana" },
|
|
103
|
+
},
|
|
104
|
+
})
|
|
105
|
+
);
|
|
106
|
+
\`\`\`
|
|
107
|
+
|
|
108
|
+
## Hono Middleware
|
|
109
|
+
|
|
110
|
+
\`\`\`typescript
|
|
111
|
+
import { Hono } from "hono";
|
|
112
|
+
import { pincerpayHono } from "@pincerpay/merchant/hono";
|
|
113
|
+
|
|
114
|
+
const app = new Hono();
|
|
115
|
+
|
|
116
|
+
app.use(
|
|
117
|
+
"*",
|
|
118
|
+
pincerpayHono({
|
|
119
|
+
apiKey: process.env.PINCERPAY_API_KEY!,
|
|
120
|
+
merchantAddress: "YOUR_SOLANA_WALLET_ADDRESS",
|
|
121
|
+
routes: {
|
|
122
|
+
"GET /api/weather": { price: "0.001", chain: "solana" },
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
);
|
|
126
|
+
\`\`\`
|
|
127
|
+
|
|
128
|
+
## Next.js (Hono Adapter)
|
|
129
|
+
|
|
130
|
+
Next.js doesn't have native x402 middleware. Use Hono as a lightweight handler in a catch-all App Router route:
|
|
131
|
+
|
|
132
|
+
\`\`\`typescript
|
|
133
|
+
// app/api/[...route]/route.ts
|
|
134
|
+
import { Hono } from "hono";
|
|
135
|
+
import { handle } from "hono/vercel";
|
|
136
|
+
import { pincerpayHono } from "@pincerpay/merchant/hono";
|
|
137
|
+
|
|
138
|
+
const app = new Hono().basePath("/api");
|
|
139
|
+
|
|
140
|
+
app.use("*", pincerpayHono({
|
|
141
|
+
apiKey: process.env.PINCERPAY_API_KEY!,
|
|
142
|
+
merchantAddress: "YOUR_SOLANA_WALLET_ADDRESS",
|
|
143
|
+
routes: {
|
|
144
|
+
"GET /api/weather": {
|
|
145
|
+
price: "0.01",
|
|
146
|
+
chain: "solana",
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
}));
|
|
150
|
+
|
|
151
|
+
app.get("/weather", (c) => {
|
|
152
|
+
return c.json({ forecast: "sunny", temp: 72 });
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
export const GET = handle(app);
|
|
156
|
+
export const POST = handle(app);
|
|
157
|
+
\`\`\`
|
|
158
|
+
|
|
159
|
+
**Notes:** \`basePath("/api")\` must match the catch-all location. Route handlers use paths relative to basePath (\`/weather\` → \`/api/weather\`). Install: \`npm install @pincerpay/merchant hono\`.
|
|
160
|
+
|
|
161
|
+
## Multi-Chain Routes
|
|
162
|
+
|
|
163
|
+
Accept payments on multiple chains per route — agents auto-select the chain they have funds on:
|
|
164
|
+
|
|
165
|
+
\`\`\`typescript
|
|
166
|
+
routes: {
|
|
167
|
+
"GET /api/weather": {
|
|
168
|
+
price: "0.01",
|
|
169
|
+
chains: ["solana", "base", "polygon"],
|
|
170
|
+
},
|
|
171
|
+
}
|
|
172
|
+
\`\`\`
|
|
173
|
+
|
|
174
|
+
If neither \`chain\` nor \`chains\` is specified, defaults to \`"solana"\`.
|
|
175
|
+
|
|
176
|
+
## Configuration
|
|
177
|
+
|
|
178
|
+
| Field | Required | Description |
|
|
179
|
+
|-------|----------|-------------|
|
|
180
|
+
| apiKey | Yes | Your PincerPay API key (\`pp_live_...\` or \`pp_test_...\`) |
|
|
181
|
+
| merchantAddress | Yes | Your USDC wallet address |
|
|
182
|
+
| facilitatorUrl | No | Custom facilitator URL (defaults to PincerPay hosted) |
|
|
183
|
+
| routes | Yes | Map of route patterns to paywall configs |
|
|
184
|
+
|
|
185
|
+
## Route Config
|
|
186
|
+
|
|
187
|
+
| Field | Required | Description |
|
|
188
|
+
|-------|----------|-------------|
|
|
189
|
+
| price | Yes | USDC price as human-readable string (e.g., "0.01" = 1 cent) |
|
|
190
|
+
| chain | No | Chain shorthand (default: "solana") |
|
|
191
|
+
| chains | No | Array of chain shorthands for multi-chain support |
|
|
192
|
+
| description | No | Human-readable description shown in 402 response |
|
|
193
|
+
|
|
194
|
+
## Utility: toBaseUnits
|
|
195
|
+
|
|
196
|
+
Convert human-readable USDC to base units (useful for spending policies):
|
|
197
|
+
|
|
198
|
+
\`\`\`typescript
|
|
199
|
+
import { toBaseUnits } from "@pincerpay/merchant";
|
|
200
|
+
toBaseUnits("0.01"); // → "10000"
|
|
201
|
+
toBaseUnits("1.00"); // → "1000000"
|
|
202
|
+
\`\`\``,
|
|
203
|
+
},
|
|
204
|
+
agent: {
|
|
205
|
+
title: "Agent Integration Guide",
|
|
206
|
+
content: `# Agent SDK Integration
|
|
207
|
+
|
|
208
|
+
## Install
|
|
209
|
+
|
|
210
|
+
\`\`\`bash
|
|
211
|
+
npm install @pincerpay/agent
|
|
212
|
+
\`\`\`
|
|
213
|
+
|
|
214
|
+
No peer dependencies — transitive deps (\`@solana/kit\`, \`viem\`, \`@x402/*\`) install automatically.
|
|
215
|
+
|
|
216
|
+
## Basic Usage
|
|
217
|
+
|
|
218
|
+
\`\`\`typescript
|
|
219
|
+
import { PincerPayAgent } from "@pincerpay/agent";
|
|
220
|
+
|
|
221
|
+
const agent = await PincerPayAgent.create({
|
|
222
|
+
chains: ["solana"],
|
|
223
|
+
solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// agent.fetch() is a drop-in replacement for fetch
|
|
227
|
+
const response = await agent.fetch("https://api.example.com/weather");
|
|
228
|
+
const data = await response.json();
|
|
229
|
+
\`\`\`
|
|
230
|
+
|
|
231
|
+
**Note:** \`PincerPayAgent.create()\` is async (required for Solana key derivation). For EVM-only agents, you can also use \`new PincerPayAgent(config)\` (synchronous).
|
|
232
|
+
|
|
233
|
+
## With Spending Policies
|
|
234
|
+
|
|
235
|
+
**Important:** Spending policies use **base units** (6 decimals), NOT human-readable amounts. \`BigInt("0.10")\` will throw at runtime!
|
|
236
|
+
|
|
237
|
+
\`\`\`typescript
|
|
238
|
+
const agent = await PincerPayAgent.create({
|
|
239
|
+
chains: ["solana"],
|
|
240
|
+
solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
241
|
+
// Spending policies use base units: 1 USDC = "1000000", $0.10 = "100000"
|
|
242
|
+
policies: [
|
|
243
|
+
{
|
|
244
|
+
maxPerTransaction: "100000", // $0.10 per API call
|
|
245
|
+
maxPerDay: "5000000", // $5.00 per day
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
});
|
|
249
|
+
\`\`\`
|
|
250
|
+
|
|
251
|
+
| Human Amount | Base Units |
|
|
252
|
+
|-------------|------------|
|
|
253
|
+
| $0.01 | \`"10000"\` |
|
|
254
|
+
| $0.10 | \`"100000"\` |
|
|
255
|
+
| $1.00 | \`"1000000"\` |
|
|
256
|
+
| $10.00 | \`"10000000"\` |
|
|
257
|
+
|
|
258
|
+
Multiply human amount × 1,000,000 to get base units. Or use \`toBaseUnits("0.10")\` from \`@pincerpay/merchant\`.
|
|
259
|
+
|
|
260
|
+
## Runtime Policy Management
|
|
261
|
+
|
|
262
|
+
\`\`\`typescript
|
|
263
|
+
// Pre-check if a payment would be allowed
|
|
264
|
+
const check = agent.checkPolicy("500000"); // 0.50 USDC
|
|
265
|
+
if (!check.allowed) console.log(check.reason);
|
|
266
|
+
|
|
267
|
+
// Update spending limits dynamically
|
|
268
|
+
agent.setPolicy({ maxPerTransaction: "5000000", maxPerDay: "50000000" });
|
|
269
|
+
|
|
270
|
+
// Monitor daily spending
|
|
271
|
+
const { date, amount } = agent.getDailySpend();
|
|
272
|
+
console.log(\`Spent \${amount} base units on \${date}\`);
|
|
273
|
+
|
|
274
|
+
// Get current policy
|
|
275
|
+
const policy = agent.getPolicy();
|
|
276
|
+
\`\`\`
|
|
277
|
+
|
|
278
|
+
## Agent Properties
|
|
279
|
+
|
|
280
|
+
| Property | Description |
|
|
281
|
+
|----------|-------------|
|
|
282
|
+
| \`agent.fetch(url, init?)\` | Payment-enabled fetch — auto-handles 402 challenges |
|
|
283
|
+
| \`agent.solanaAddress\` | Agent's Solana public key (only available via \`.create()\`) |
|
|
284
|
+
| \`agent.evmAddress\` | Agent's EVM public address |
|
|
285
|
+
| \`agent.chains\` | Configured chain shorthands |
|
|
286
|
+
| \`agent.checkPolicy(amountBaseUnits)\` | Pre-check \`{ allowed, reason? }\` against spending limits |
|
|
287
|
+
| \`agent.setPolicy(policy)\` | Replace spending policy at runtime |
|
|
288
|
+
| \`agent.getPolicy()\` | Get current spending policy |
|
|
289
|
+
| \`agent.getDailySpend()\` | Get \`{ date: string, amount: bigint }\` for today's tracked spend |
|
|
290
|
+
|
|
291
|
+
## How x402 Payment Flow Works
|
|
292
|
+
|
|
293
|
+
1. \`agent.fetch(url)\` calls the merchant API
|
|
294
|
+
2. Server returns HTTP 402 with \`X-Payment\` header (x402 challenge)
|
|
295
|
+
3. Agent SDK extracts payment requirements (amount, chain, recipient)
|
|
296
|
+
4. Agent signs a USDC transfer transaction
|
|
297
|
+
5. PincerPay facilitator verifies + broadcasts the transaction
|
|
298
|
+
6. Agent retries the original request with the payment proof
|
|
299
|
+
7. Server validates payment and returns the protected resource
|
|
300
|
+
|
|
301
|
+
## Multi-Chain Support
|
|
302
|
+
|
|
303
|
+
\`\`\`typescript
|
|
304
|
+
const agent = await PincerPayAgent.create({
|
|
305
|
+
chains: ["solana", "base"],
|
|
306
|
+
solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
307
|
+
evmPrivateKey: process.env.AGENT_EVM_KEY!,
|
|
308
|
+
});
|
|
309
|
+
\`\`\`
|
|
310
|
+
|
|
311
|
+
The agent automatically selects the correct chain based on the merchant's 402 response.
|
|
312
|
+
|
|
313
|
+
## Environment Variables
|
|
314
|
+
|
|
315
|
+
\`\`\`
|
|
316
|
+
AGENT_SOLANA_KEY=your_base58_private_key_here
|
|
317
|
+
# or for EVM:
|
|
318
|
+
AGENT_EVM_KEY=0xyour_hex_private_key_here
|
|
319
|
+
\`\`\`
|
|
320
|
+
|
|
321
|
+
**Never commit private keys.** Ensure \`.env*\` is in \`.gitignore\`.`,
|
|
322
|
+
},
|
|
323
|
+
troubleshooting: {
|
|
324
|
+
title: "Troubleshooting Common Issues",
|
|
325
|
+
content: `# Troubleshooting
|
|
326
|
+
|
|
327
|
+
## Common Issues
|
|
328
|
+
|
|
329
|
+
| Symptom | Cause | Fix |
|
|
330
|
+
|---------|-------|-----|
|
|
331
|
+
| \`ERR_MODULE_NOT_FOUND\` | ESM import issues | Add \`"type": "module"\` to package.json or use \`.mts\` extension. Both \`@pincerpay/merchant\` and \`@pincerpay/agent\` are ESM-only. |
|
|
332
|
+
| \`SyntaxError: Cannot use import statement\` | CommonJS project importing ESM | Add \`"type": "module"\` to package.json. |
|
|
333
|
+
| 402 but no payment attempted | Chain mismatch | Agent and merchant must use the same chain (e.g., both \`"solana-devnet"\`). Check \`chains\` array. |
|
|
334
|
+
| \`Invalid base58 character\` | Wrong key format for Solana | Solana private keys are base58 (alphanumeric, no \`0x\` prefix). EVM keys are hex (\`0x...\`). |
|
|
335
|
+
| Payment succeeds but 402 persists | Facilitator URL mismatch | Both merchant and agent must use the same facilitator. Default: \`https://facilitator.pincerpay.com\`. |
|
|
336
|
+
| \`Exceeds per-transaction limit\` | Spending policy too restrictive | Increase \`maxPerTransaction\` — value is in **base units** (6 decimals). \`"1000000"\` = $1.00 USDC. |
|
|
337
|
+
| \`BigInt("0.10")\` throws | Human-readable amount in policy | Policies use base units, not human amounts. Use \`"100000"\` not \`"0.10"\` for $0.10. |
|
|
338
|
+
| \`At least one wallet key required\` | No private key configured | Set \`solanaPrivateKey\` or \`evmPrivateKey\` in agent config. Check \`.env\` is loaded. |
|
|
339
|
+
| Route not matching for 402 | Wrong route pattern format | Pattern must be \`"METHOD /path"\` — e.g., \`"GET /api/weather"\`. Uppercase method, space, leading slash. |
|
|
340
|
+
| \`pp_live_\` key on devnet | API key environment mismatch | Use \`pp_test_\` keys for devnet chains. |
|
|
341
|
+
|
|
342
|
+
## Devnet Funding
|
|
343
|
+
|
|
344
|
+
- **Solana devnet SOL**: https://faucet.solana.com
|
|
345
|
+
- **Solana devnet USDC**: Request from PincerPay team or use a devnet DEX
|
|
346
|
+
- **Base Sepolia ETH**: Base Sepolia faucet
|
|
347
|
+
- **Base Sepolia USDC**: Circle testnet USDC faucet
|
|
348
|
+
|
|
349
|
+
## Debugging Tips
|
|
350
|
+
|
|
351
|
+
1. **Verify 402 response**: \`curl -s -w "\\nHTTP Status: %{http_code}\\n" http://localhost:3000/api/endpoint\` — should return 402 with \`paymentRequirements\` JSON
|
|
352
|
+
2. **Check chain match**: Both merchant route config and agent \`chains\` array must use identical chain shorthands
|
|
353
|
+
3. **Test agent fetch**: \`const response = await agent.fetch(url); console.log(response.status);\` — should be 200 after payment
|
|
354
|
+
4. **Inspect spending**: \`console.log(agent.getDailySpend())\` to see current daily spend tracking
|
|
355
|
+
5. **Validate config**: Use the \`validate-payment-config\` MCP tool to check your merchant config for errors`,
|
|
356
|
+
},
|
|
357
|
+
reference: {
|
|
358
|
+
title: "API Reference",
|
|
359
|
+
content: `# PincerPay Reference
|
|
360
|
+
|
|
361
|
+
## Chain Shorthands
|
|
362
|
+
|
|
363
|
+
| Shorthand | Network | CAIP-2 ID | Notes |
|
|
364
|
+
|-----------|---------|-----------|-------|
|
|
365
|
+
| \`solana\` | Solana Mainnet | \`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\` | Primary chain, default |
|
|
366
|
+
| \`solana-devnet\` | Solana Devnet | \`solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\` | Solana testnet |
|
|
367
|
+
| \`base\` | Base Mainnet | \`eip155:8453\` | EVM, low fees |
|
|
368
|
+
| \`base-sepolia\` | Base Sepolia | \`eip155:84532\` | EVM testnet |
|
|
369
|
+
| \`polygon\` | Polygon Mainnet | \`eip155:137\` | EVM |
|
|
370
|
+
| \`polygon-amoy\` | Polygon Amoy | \`eip155:80002\` | Polygon testnet |
|
|
371
|
+
|
|
372
|
+
## USDC Amounts (6 Decimals)
|
|
373
|
+
|
|
374
|
+
Route \`price\` fields use human-readable strings. Spending \`policies\` use base unit strings.
|
|
375
|
+
|
|
376
|
+
| Human Amount | Base Units | Route \`price\` | Policy value |
|
|
377
|
+
|-------------|------------|---------------|--------------|
|
|
378
|
+
| $0.001 | 1,000 | \`"0.001"\` | \`"1000"\` |
|
|
379
|
+
| $0.01 | 10,000 | \`"0.01"\` | \`"10000"\` |
|
|
380
|
+
| $0.10 | 100,000 | \`"0.10"\` | \`"100000"\` |
|
|
381
|
+
| $1.00 | 1,000,000 | \`"1.00"\` | \`"1000000"\` |
|
|
382
|
+
| $10.00 | 10,000,000 | \`"10.00"\` | \`"10000000"\` |
|
|
383
|
+
| $100.00 | 100,000,000 | \`"100.00"\` | \`"100000000"\` |
|
|
384
|
+
|
|
385
|
+
Convert: multiply human amount × 1,000,000. Or use \`toBaseUnits("0.01")\` from \`@pincerpay/merchant\`.
|
|
386
|
+
|
|
387
|
+
## Package Exports
|
|
388
|
+
|
|
389
|
+
| Package | Key Exports |
|
|
390
|
+
|---------|-------------|
|
|
391
|
+
| \`@pincerpay/merchant\` | \`pincerpay\` (Express), \`pincerpayHono\` (Hono), \`PincerPayClient\` (low-level), \`toBaseUnits\`, \`resolveRouteChains\`, \`getUsdcAsset\` |
|
|
392
|
+
| \`@pincerpay/merchant/express\` | \`pincerpay\` (tree-shakeable sub-path import) |
|
|
393
|
+
| \`@pincerpay/merchant/hono\` | \`pincerpayHono\` (tree-shakeable sub-path import) |
|
|
394
|
+
| \`@pincerpay/agent\` | \`PincerPayAgent\` (main agent class), \`SolanaSmartAgent\` (Squads session keys — advanced) |
|
|
395
|
+
| \`@pincerpay/core\` | \`PincerPayConfig\`, \`AgentConfig\`, \`SpendingPolicy\`, \`RoutePaywallConfig\`, \`ChainConfig\` (types) |
|
|
396
|
+
|
|
397
|
+
## PincerPayClient Methods (Low-Level)
|
|
398
|
+
|
|
399
|
+
For advanced users building custom middleware:
|
|
400
|
+
|
|
401
|
+
| Method | Description |
|
|
402
|
+
|--------|-------------|
|
|
403
|
+
| \`verify(paymentPayload, paymentRequirements)\` | Verify a raw x402 payment payload |
|
|
404
|
+
| \`settle(paymentPayload, paymentRequirements)\` | Settle a verified payment on-chain |
|
|
405
|
+
| \`getSupported()\` | Get supported schemes/networks from the facilitator |
|
|
406
|
+
| \`getStatus(txHash)\` | Get transaction status by hash |
|
|
407
|
+
|
|
408
|
+
Most users should use \`pincerpay()\` or \`pincerpayHono()\` middleware instead.
|
|
409
|
+
|
|
410
|
+
## PincerPayAgent Properties & Methods
|
|
411
|
+
|
|
412
|
+
| Member | Description |
|
|
413
|
+
|--------|-------------|
|
|
414
|
+
| \`agent.fetch(url, init?)\` | Payment-enabled fetch — auto-handles 402 challenges |
|
|
415
|
+
| \`agent.solanaAddress\` | Agent's Solana public key (only via \`.create()\`) |
|
|
416
|
+
| \`agent.evmAddress\` | Agent's EVM public address |
|
|
417
|
+
| \`agent.chains\` | Configured chain shorthands |
|
|
418
|
+
| \`agent.checkPolicy(amountBaseUnits)\` | Pre-check \`{ allowed, reason? }\` against spending limits |
|
|
419
|
+
| \`agent.setPolicy(policy)\` | Replace spending policy at runtime |
|
|
420
|
+
| \`agent.getPolicy()\` | Get current spending policy |
|
|
421
|
+
| \`agent.getDailySpend()\` | Get \`{ date: string, amount: bigint }\` for today's tracked spend |
|
|
422
|
+
|
|
423
|
+
## Route Pattern Format
|
|
424
|
+
|
|
425
|
+
Route patterns must follow this format: \`"METHOD /path"\`
|
|
426
|
+
|
|
427
|
+
- **Method**: Uppercase HTTP method (GET, POST, PUT, DELETE, PATCH)
|
|
428
|
+
- **Space**: Single space between method and path
|
|
429
|
+
- **Path**: Must start with \`/\`
|
|
430
|
+
|
|
431
|
+
Examples: \`"GET /api/weather"\`, \`"POST /api/submit"\`, \`"GET /api/data/:id"\``,
|
|
432
|
+
},
|
|
433
|
+
};
|
|
434
|
+
export function registerDocsResources(server) {
|
|
435
|
+
const topics = Object.keys(DOCS);
|
|
436
|
+
server.resource("docs", new ResourceTemplate("docs://pincerpay/{topic}", {
|
|
437
|
+
list: async () => ({
|
|
438
|
+
resources: topics.map((key) => ({
|
|
439
|
+
uri: `docs://pincerpay/${key}`,
|
|
440
|
+
name: DOCS[key].title,
|
|
441
|
+
mimeType: "text/markdown",
|
|
442
|
+
})),
|
|
443
|
+
}),
|
|
444
|
+
}), async (uri, { topic }) => {
|
|
445
|
+
const doc = DOCS[topic];
|
|
446
|
+
if (!doc) {
|
|
447
|
+
throw new Error(`Unknown doc topic: "${topic}". Available: ${topics.join(", ")}`);
|
|
448
|
+
}
|
|
449
|
+
return {
|
|
450
|
+
contents: [
|
|
451
|
+
{
|
|
452
|
+
uri: uri.href,
|
|
453
|
+
text: doc.content,
|
|
454
|
+
mimeType: "text/markdown",
|
|
455
|
+
},
|
|
456
|
+
],
|
|
457
|
+
};
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
//# sourceMappingURL=docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/resources/docs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAE3E,MAAM,IAAI,GAAuD;IAC/D,iBAAiB,EAAE;QACjB,KAAK,EAAE,gCAAgC;QACvC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+HAqEkH;KAC5H;IACD,QAAQ,EAAE;QACR,KAAK,EAAE,4BAA4B;QACnC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4HN;KACJ;IACD,KAAK,EAAE;QACL,KAAK,EAAE,yBAAyB;QAChC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sEAmHyD;KACnE;IACD,eAAe,EAAE;QACf,KAAK,EAAE,+BAA+B;QACtC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8GA8BiG;KAC3G;IACD,SAAS,EAAE;QACT,KAAK,EAAE,eAAe;QACtB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kFAwEqE;KAC/E;CACF,CAAC;AAEF,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEjC,MAAM,CAAC,QAAQ,CACb,MAAM,EACN,IAAI,gBAAgB,CAAC,0BAA0B,EAAE;QAC/C,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACjB,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBAC9B,GAAG,EAAE,oBAAoB,GAAG,EAAE;gBAC9B,IAAI,EAAE,IAAI,CAAC,GAAG,CAAE,CAAC,KAAK;gBACtB,QAAQ,EAAE,eAAwB;aACnC,CAAC,CAAC;SACJ,CAAC;KACH,CAAC,EACF,KAAK,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAe,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CACb,uBAAuB,KAAK,iBAAiB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACjE,CAAC;QACJ,CAAC;QACD,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,IAAI,EAAE,GAAG,CAAC,OAAO;oBACjB,QAAQ,EAAE,eAAe;iBAC1B;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAKtD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,iBAAiB,QAK1B"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { registerChainResources } from "./chain-config.js";
|
|
2
|
+
import { registerOpenApiResource } from "./openapi-spec.js";
|
|
3
|
+
import { registerDocsResources } from "./docs.js";
|
|
4
|
+
export function registerResources(server, client) {
|
|
5
|
+
registerChainResources(server);
|
|
6
|
+
registerOpenApiResource(server, client);
|
|
7
|
+
registerDocsResources(server);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,UAAU,iBAAiB,CAC/B,MAAiB,EACjB,MAAyB;IAEzB,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { FacilitatorClient } from "../client.js";
|
|
3
|
+
export declare function registerOpenApiResource(server: McpServer, client: FacilitatorClient): void;
|
|
4
|
+
//# sourceMappingURL=openapi-spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi-spec.d.ts","sourceRoot":"","sources":["../../src/resources/openapi-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,iBAAiB,QA8B1B"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function registerOpenApiResource(server, client) {
|
|
2
|
+
server.resource("openapi-spec", "pincerpay://openapi", async (uri) => {
|
|
3
|
+
try {
|
|
4
|
+
const spec = await client.getOpenApiSpec();
|
|
5
|
+
return {
|
|
6
|
+
contents: [
|
|
7
|
+
{
|
|
8
|
+
uri: uri.href,
|
|
9
|
+
text: JSON.stringify(spec, null, 2),
|
|
10
|
+
mimeType: "application/json",
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
return {
|
|
17
|
+
contents: [
|
|
18
|
+
{
|
|
19
|
+
uri: uri.href,
|
|
20
|
+
text: `Failed to fetch OpenAPI spec: ${err instanceof Error ? err.message : String(err)}`,
|
|
21
|
+
mimeType: "text/plain",
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=openapi-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi-spec.js","sourceRoot":"","sources":["../../src/resources/openapi-spec.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,uBAAuB,CACrC,MAAiB,EACjB,MAAyB;IAEzB,MAAM,CAAC,QAAQ,CACb,cAAc,EACd,qBAAqB,EACrB,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;YAC3C,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;wBACnC,QAAQ,EAAE,kBAAkB;qBAC7B;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,IAAI,EAAE,iCAAiC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;wBACzF,QAAQ,EAAE,YAAY;qBACvB;iBACF;aACF,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export interface PincerPayMcpConfig {
|
|
3
|
+
/** PincerPay API key (pp_live_... or pp_test_...) */
|
|
4
|
+
apiKey?: string;
|
|
5
|
+
/** Facilitator URL (defaults to https://facilitator.pincerpay.com) */
|
|
6
|
+
facilitatorUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Create a configured PincerPay MCP server with all tools,
|
|
10
|
+
* resources, and prompts registered.
|
|
11
|
+
*
|
|
12
|
+
* Tools that don't require auth (scaffolding, gas estimates,
|
|
13
|
+
* chain listing) work without an API key. Operations tools
|
|
14
|
+
* (transaction status) require a key and return a helpful error
|
|
15
|
+
* if none is configured.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createPincerPayMcpServer(config?: PincerPayMcpConfig): McpServer;
|
|
18
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,GAAE,kBAAuB,aAuCvE"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { FacilitatorClient } from "./client.js";
|
|
3
|
+
import { registerTools } from "./tools/index.js";
|
|
4
|
+
import { registerResources } from "./resources/index.js";
|
|
5
|
+
import { registerPrompts } from "./prompts/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Create a configured PincerPay MCP server with all tools,
|
|
8
|
+
* resources, and prompts registered.
|
|
9
|
+
*
|
|
10
|
+
* Tools that don't require auth (scaffolding, gas estimates,
|
|
11
|
+
* chain listing) work without an API key. Operations tools
|
|
12
|
+
* (transaction status) require a key and return a helpful error
|
|
13
|
+
* if none is configured.
|
|
14
|
+
*/
|
|
15
|
+
export function createPincerPayMcpServer(config = {}) {
|
|
16
|
+
const server = new McpServer({
|
|
17
|
+
name: "pincerpay",
|
|
18
|
+
version: "0.1.0",
|
|
19
|
+
}, {
|
|
20
|
+
instructions: "PincerPay is an on-chain USDC payment gateway for AI agents — no card rails, " +
|
|
21
|
+
"pure stablecoin settlement via the x402 protocol (HTTP 402). Solana is the primary " +
|
|
22
|
+
"chain; Base and Polygon are optional EVM alternatives.\n\n" +
|
|
23
|
+
"ROLE ROUTING: When a user wants to integrate PincerPay, first determine their role:\n" +
|
|
24
|
+
"- Merchant (accept payments): use the `integrate-merchant` prompt → scaffold-x402-middleware → validate-payment-config → generate-ucp-manifest\n" +
|
|
25
|
+
"- Agent developer (make payments): use the `integrate-agent` prompt → scaffold-agent-client → estimate-gas-cost\n" +
|
|
26
|
+
"- Unclear: use the `get-started` prompt to triage\n" +
|
|
27
|
+
"- Debugging: use the `debug-transaction` prompt\n\n" +
|
|
28
|
+
"KEY GOTCHAS to always warn about:\n" +
|
|
29
|
+
"1. Route `price` uses human-readable USDC (\"0.01\"), but spending `policies` use base units with 6 decimals (\"10000\" = $0.01). Using \"0.10\" in a policy causes BigInt() to throw.\n" +
|
|
30
|
+
"2. ESM required: \"type\": \"module\" in package.json — SDKs are ESM-only.\n" +
|
|
31
|
+
"3. Security: .gitignore must include .env* — never commit API keys or private keys.\n" +
|
|
32
|
+
"4. Use devnet chains for testing (solana-devnet, base-sepolia).\n\n" +
|
|
33
|
+
"Docs resources: docs://pincerpay/getting-started, docs://pincerpay/merchant, " +
|
|
34
|
+
"docs://pincerpay/agent, docs://pincerpay/troubleshooting, docs://pincerpay/reference.",
|
|
35
|
+
capabilities: {
|
|
36
|
+
logging: {},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
const client = new FacilitatorClient({
|
|
40
|
+
apiKey: config.apiKey,
|
|
41
|
+
facilitatorUrl: config.facilitatorUrl,
|
|
42
|
+
});
|
|
43
|
+
registerTools(server, client);
|
|
44
|
+
registerResources(server, client);
|
|
45
|
+
registerPrompts(server);
|
|
46
|
+
return server;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AASrD;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB,CAAC,SAA6B,EAAE;IACtE,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EACV,+EAA+E;YAC/E,qFAAqF;YACrF,4DAA4D;YAC5D,uFAAuF;YACvF,kJAAkJ;YAClJ,mHAAmH;YACnH,qDAAqD;YACrD,qDAAqD;YACrD,qCAAqC;YACrC,0LAA0L;YAC1L,8EAA8E;YAC9E,uFAAuF;YACvF,qEAAqE;YACrE,+EAA+E;YAC/E,uFAAuF;QACzF,YAAY,EAAE;YACZ,OAAO,EAAE,EAAE;SACZ;KACF,CACF,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC;QACnC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,cAAc,EAAE,MAAM,CAAC,cAAc;KACtC,CAAC,CAAC;IAEH,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,eAAe,CAAC,MAAM,CAAC,CAAC;IAExB,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { FacilitatorClient } from "../client.js";
|
|
3
|
+
export declare function registerCheckTransaction(server: McpServer, client: FacilitatorClient): void;
|
|
4
|
+
//# sourceMappingURL=check-transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-transaction.d.ts","sourceRoot":"","sources":["../../src/tools/check-transaction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAWtD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,iBAAiB,QA8C1B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const inputSchema = {
|
|
3
|
+
txHash: z
|
|
4
|
+
.string()
|
|
5
|
+
.min(1)
|
|
6
|
+
.describe("Transaction hash (EVM hex) or signature (Solana base58) to look up."),
|
|
7
|
+
};
|
|
8
|
+
export function registerCheckTransaction(server, client) {
|
|
9
|
+
server.tool("check-transaction-status", "Query the PincerPay facilitator for the status of a payment transaction. " +
|
|
10
|
+
"Returns chain, amount, addresses, status (pending/mempool/optimistic/confirmed/failed), " +
|
|
11
|
+
"and timestamps. Requires a PincerPay API key.", inputSchema, async ({ txHash }) => {
|
|
12
|
+
try {
|
|
13
|
+
client.requireAuth();
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: "text",
|
|
20
|
+
text: err instanceof Error ? err.message : String(err),
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
isError: true,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const result = await client.getStatus(txHash);
|
|
28
|
+
return {
|
|
29
|
+
content: [
|
|
30
|
+
{
|
|
31
|
+
type: "text",
|
|
32
|
+
text: JSON.stringify(result, null, 2),
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: "text",
|
|
42
|
+
text: `Failed to fetch transaction status: ${err instanceof Error ? err.message : String(err)}`,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
isError: true,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=check-transaction.js.map
|