@silencelaboratories/pay-mcp-client 1.0.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/README.md +76 -0
- package/build/index.js +209 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Pay MCP Client
|
|
2
|
+
|
|
3
|
+
Model Context Protocol (MCP) client for AI-powered payment operations. Connects LLMs to the Pay Server for payment operations.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm run build
|
|
10
|
+
npm start
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Cursor Configuration
|
|
14
|
+
|
|
15
|
+
Add to `~/.cursor/mcp.json`:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"wallet-mcp-server": {
|
|
21
|
+
"command": "node",
|
|
22
|
+
"args": ["/path/to/mcp-server/build/index.js"],
|
|
23
|
+
"env": {
|
|
24
|
+
"WALLET_API_URL": "http://localhost:3001"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Available Tools
|
|
32
|
+
|
|
33
|
+
### Utility Tools
|
|
34
|
+
|
|
35
|
+
| Tool | Description |
|
|
36
|
+
|------|-------------|
|
|
37
|
+
| `get_time` | Get current date and time |
|
|
38
|
+
| `add` | Add two numbers together |
|
|
39
|
+
|
|
40
|
+
### Wallet Tools
|
|
41
|
+
|
|
42
|
+
| Tool | Description | Parameters |
|
|
43
|
+
|------|-------------|------------|
|
|
44
|
+
| `get_eth_balance` | Get ETH balance for wallet | `token` |
|
|
45
|
+
| `sign_eth_transaction` | Sign and broadcast ETH transaction | `token`, `recipientAddress`, `amount` |
|
|
46
|
+
| `get_transaction_history` | Get transaction history | `token` |
|
|
47
|
+
|
|
48
|
+
### Supplier Tools
|
|
49
|
+
|
|
50
|
+
| Tool | Description | Parameters |
|
|
51
|
+
|------|-------------|------------|
|
|
52
|
+
| `get_suppliers` | Get list of available suppliers | - |
|
|
53
|
+
| `get_supplier` | Get supplier details by ID | `supplierId` |
|
|
54
|
+
| `pay_supplier` | Pay a supplier by ID | `token`, `supplierId`, `amount` |
|
|
55
|
+
|
|
56
|
+
## Token Format
|
|
57
|
+
|
|
58
|
+
The bearer token is 168 characters:
|
|
59
|
+
- `ephSk` (64 chars): Ephemeral secret key hex
|
|
60
|
+
- `keyId` (64 chars): MPC key ID
|
|
61
|
+
- `address` (40 chars): Wallet address (without 0x)
|
|
62
|
+
|
|
63
|
+
## Example Usage
|
|
64
|
+
|
|
65
|
+
Once connected to Cursor, you can use natural language:
|
|
66
|
+
|
|
67
|
+
- "What's my ETH balance?" (provide token)
|
|
68
|
+
- "Send 0.001 ETH to 0x..." (provide token)
|
|
69
|
+
- "Show my transaction history" (provide token)
|
|
70
|
+
- "List available suppliers"
|
|
71
|
+
- "Pay Amazon 0.01 ETH" (provide token)
|
|
72
|
+
|
|
73
|
+
## Dependencies
|
|
74
|
+
|
|
75
|
+
- `@modelcontextprotocol/sdk` - MCP SDK
|
|
76
|
+
- Requires `wallet-api` running on `http://localhost:3001`
|
package/build/index.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
const server = new McpServer({
|
|
5
|
+
name: "@silencelaboratories/pay-mcp-client",
|
|
6
|
+
version: "1.0.0",
|
|
7
|
+
});
|
|
8
|
+
const WALLET_API_URL = process.env.WALLET_API_URL || "http://localhost:3001";
|
|
9
|
+
async function callWalletApi(endpoint, method, token, body) {
|
|
10
|
+
const url = `${WALLET_API_URL}${endpoint}`;
|
|
11
|
+
const headers = {
|
|
12
|
+
"Content-Type": "application/json",
|
|
13
|
+
};
|
|
14
|
+
if (token) {
|
|
15
|
+
headers.Authorization = `Bearer ${token}`;
|
|
16
|
+
}
|
|
17
|
+
const response = await fetch(url, {
|
|
18
|
+
method,
|
|
19
|
+
headers,
|
|
20
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
21
|
+
});
|
|
22
|
+
return response.json();
|
|
23
|
+
}
|
|
24
|
+
// Tool 1: get_eth_balance - get ETH balance for wallet
|
|
25
|
+
server.tool("get_eth_balance", "Get ETH balance for the wallet associated with the token", {
|
|
26
|
+
token: z.string().describe("Bearer token (168 chars: ephSk + keyId + address)"),
|
|
27
|
+
}, async ({ token }) => {
|
|
28
|
+
try {
|
|
29
|
+
const result = await callWalletApi("/api/balance/eth", "GET", token);
|
|
30
|
+
return {
|
|
31
|
+
content: [
|
|
32
|
+
{
|
|
33
|
+
type: "text",
|
|
34
|
+
text: JSON.stringify(result),
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
return {
|
|
41
|
+
content: [
|
|
42
|
+
{
|
|
43
|
+
type: "text",
|
|
44
|
+
text: JSON.stringify({ success: false, error: error.message }),
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
// Tool 2: sign_eth_transaction - sign and broadcast ETH transaction
|
|
51
|
+
server.tool("sign_eth_transaction", "Sign and broadcast an ETH transaction using MPC signing", {
|
|
52
|
+
token: z.string().describe("Bearer token (168 chars: ephSk + keyId + address)"),
|
|
53
|
+
recipientAddress: z.string().describe("Recipient wallet address"),
|
|
54
|
+
amount: z.string().describe("Amount in ETH (e.g., '0.001')"),
|
|
55
|
+
}, async ({ token, recipientAddress, amount }) => {
|
|
56
|
+
try {
|
|
57
|
+
const result = await callWalletApi("/api/sign/eth", "POST", token, {
|
|
58
|
+
recipientAddress,
|
|
59
|
+
amount,
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: "text",
|
|
65
|
+
text: JSON.stringify(result),
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
return {
|
|
72
|
+
content: [
|
|
73
|
+
{
|
|
74
|
+
type: "text",
|
|
75
|
+
text: JSON.stringify({ success: false, error: error.message }),
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
// Tool 3: get_transaction_history - get transaction history for wallet
|
|
82
|
+
server.tool("get_transaction_history", "Get transaction history for the wallet associated with the token", {
|
|
83
|
+
token: z.string().describe("Bearer token (168 chars: ephSk + keyId + address)"),
|
|
84
|
+
}, async ({ token }) => {
|
|
85
|
+
try {
|
|
86
|
+
const result = await callWalletApi("/api/transactions/eth", "GET", token);
|
|
87
|
+
return {
|
|
88
|
+
content: [
|
|
89
|
+
{
|
|
90
|
+
type: "text",
|
|
91
|
+
text: JSON.stringify(result),
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return {
|
|
98
|
+
content: [
|
|
99
|
+
{
|
|
100
|
+
type: "text",
|
|
101
|
+
text: JSON.stringify({ success: false, error: error.message }),
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
// Tool 4: get_suppliers - get list of available suppliers
|
|
108
|
+
server.tool("get_suppliers", "Get list of available suppliers/merchants that can receive payments", {}, async () => {
|
|
109
|
+
try {
|
|
110
|
+
const result = await callWalletApi("/api/suppliers", "GET");
|
|
111
|
+
return {
|
|
112
|
+
content: [
|
|
113
|
+
{
|
|
114
|
+
type: "text",
|
|
115
|
+
text: JSON.stringify(result),
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
return {
|
|
122
|
+
content: [
|
|
123
|
+
{
|
|
124
|
+
type: "text",
|
|
125
|
+
text: JSON.stringify({ success: false, error: error.message }),
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
// Tool 5: get_supplier - get specific supplier by ID
|
|
132
|
+
server.tool("get_supplier", "Get details of a specific supplier by ID", {
|
|
133
|
+
supplierId: z.string().describe("Supplier ID (e.g., 'amazon', 'gemini', 'apollo')"),
|
|
134
|
+
}, async ({ supplierId }) => {
|
|
135
|
+
try {
|
|
136
|
+
const result = await callWalletApi(`/api/suppliers/${supplierId}`, "GET");
|
|
137
|
+
return {
|
|
138
|
+
content: [
|
|
139
|
+
{
|
|
140
|
+
type: "text",
|
|
141
|
+
text: JSON.stringify(result),
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
return {
|
|
148
|
+
content: [
|
|
149
|
+
{
|
|
150
|
+
type: "text",
|
|
151
|
+
text: JSON.stringify({ success: false, error: error.message }),
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
// Tool 6: pay_supplier - pay a supplier by ID
|
|
158
|
+
server.tool("pay_supplier", "Pay a supplier/merchant by their ID using MPC signing", {
|
|
159
|
+
token: z.string().describe("Bearer token (168 chars: ephSk + keyId + address)"),
|
|
160
|
+
supplierId: z.string().describe("Supplier ID (e.g., 'amazon', 'gemini', 'apollo')"),
|
|
161
|
+
amount: z.string().describe("Amount in ETH (e.g., '0.001')"),
|
|
162
|
+
}, async ({ token, supplierId, amount }) => {
|
|
163
|
+
try {
|
|
164
|
+
// First get the supplier address
|
|
165
|
+
const supplierResult = await callWalletApi(`/api/suppliers/${supplierId}`, "GET");
|
|
166
|
+
if (!supplierResult.success) {
|
|
167
|
+
return {
|
|
168
|
+
content: [
|
|
169
|
+
{
|
|
170
|
+
type: "text",
|
|
171
|
+
text: JSON.stringify({ success: false, error: `Supplier '${supplierId}' not found` }),
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
// Then sign and send the transaction
|
|
177
|
+
const result = await callWalletApi("/api/sign/eth", "POST", token, {
|
|
178
|
+
recipientAddress: supplierResult.supplier.address,
|
|
179
|
+
amount,
|
|
180
|
+
});
|
|
181
|
+
return {
|
|
182
|
+
content: [
|
|
183
|
+
{
|
|
184
|
+
type: "text",
|
|
185
|
+
text: JSON.stringify({
|
|
186
|
+
...result,
|
|
187
|
+
supplier: supplierResult.supplier.name,
|
|
188
|
+
}),
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
return {
|
|
195
|
+
content: [
|
|
196
|
+
{
|
|
197
|
+
type: "text",
|
|
198
|
+
text: JSON.stringify({ success: false, error: error.message }),
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
async function main() {
|
|
205
|
+
const transport = new StdioServerTransport();
|
|
206
|
+
await server.connect(transport);
|
|
207
|
+
console.error("Wallet MCP Server running on stdio");
|
|
208
|
+
}
|
|
209
|
+
main().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@silencelaboratories/pay-mcp-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"build"
|
|
8
|
+
],
|
|
9
|
+
"bin": {
|
|
10
|
+
"pay-mcp-client": "build/index.js"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"start": "node build/index.js",
|
|
18
|
+
"dev": "tsc && node build/index.js"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@modelcontextprotocol/sdk": "^1.12.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^22.0.0",
|
|
25
|
+
"typescript": "^5.7.0"
|
|
26
|
+
}
|
|
27
|
+
}
|