@phantom/mcp-server 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/README.md +498 -0
- package/bin/phantom-mcp +2 -0
- package/dist/index.d.ts +128 -0
- package/dist/index.js +1448 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
# @phantom/mcp-server
|
|
2
|
+
|
|
3
|
+
> **⚠️ PREVIEW DISCLAIMER**
|
|
4
|
+
>
|
|
5
|
+
> This MCP server is currently in **preview** and may break or change at any time without notice. Early adopters should **always use a separate Phantom account** specifically for testing with AI agents.
|
|
6
|
+
>
|
|
7
|
+
> **Phantom makes no guarantees whatsoever around anything your agent may do using this MCP server.** Use at your own risk and never use accounts containing significant assets.
|
|
8
|
+
|
|
9
|
+
An MCP (Model Context Protocol) server that provides LLMs like Claude with direct access to Phantom wallet operations. This enables AI assistants to interact with embedded wallets, view addresses, sign transactions, and sign messages across multiple blockchain networks (Solana, Ethereum, Bitcoin, Sui) through natural language interactions.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **SSO Authentication**: Seamless integration with Phantom's embedded wallet SSO flow (Google/Apple login)
|
|
14
|
+
- **Session Persistence**: Automatic session management with stamper keys stored in `~/.phantom-mcp/session.json`
|
|
15
|
+
- **Multi-Chain Support**: Works with Solana, Ethereum, Bitcoin, and Sui networks
|
|
16
|
+
- **Three MCP Tools**:
|
|
17
|
+
- `get_wallet_addresses` - Get blockchain addresses for the authenticated embedded wallet
|
|
18
|
+
- `sign_transaction` - Sign transactions across supported chains
|
|
19
|
+
- `sign_message` - Sign UTF-8 messages with automatic chain-specific routing
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
### Option 1: npx (Recommended)
|
|
24
|
+
|
|
25
|
+
Use npx to run the server without global installation. This ensures you always use the latest version:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx -y @phantom/mcp-server
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Option 2: Global Install
|
|
32
|
+
|
|
33
|
+
Install the package globally for faster startup:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install -g @phantom/mcp-server
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then run:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
phantom-mcp
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Getting Your App ID
|
|
46
|
+
|
|
47
|
+
**Important:** Before you can use the MCP server, you must obtain an App ID from the Phantom Portal. This is required for the early release.
|
|
48
|
+
|
|
49
|
+
### Steps to Get Your App ID:
|
|
50
|
+
|
|
51
|
+
1. **Visit the Phantom Portal**: Go to [phantom.com/portal](https://phantom.com/portal)
|
|
52
|
+
2. **Sign in**: Use your Gmail or Apple account to sign in
|
|
53
|
+
3. **Create an App**: Click "Create App" and fill in the required details
|
|
54
|
+
4. **Get Your App ID**: Navigate to the "Phantom Connect" tab to find your App ID
|
|
55
|
+
- Your app is automatically approved for development use
|
|
56
|
+
- Copy the App ID for use in the MCP server configuration
|
|
57
|
+
|
|
58
|
+
**Important Note:** The email you use to sign in to the Phantom Portal **must match** the email you use when authenticating in the MCP server. If these don't match, authentication will fail.
|
|
59
|
+
|
|
60
|
+
Once you have your App ID, you can proceed with the configuration below.
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
### Claude Desktop Configuration
|
|
65
|
+
|
|
66
|
+
Add the MCP server to your Claude Desktop configuration file:
|
|
67
|
+
|
|
68
|
+
**Location:**
|
|
69
|
+
|
|
70
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
71
|
+
- Windows: `%APPDATA%/Claude/claude_desktop_config.json`
|
|
72
|
+
|
|
73
|
+
**Using npx (Recommended):**
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"phantom": {
|
|
79
|
+
"command": "npx",
|
|
80
|
+
"args": ["-y", "@phantom/mcp-server"],
|
|
81
|
+
"env": {
|
|
82
|
+
"PHANTOM_APP_ID": "your_app_id_from_portal"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Using global install:**
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"mcpServers": {
|
|
94
|
+
"phantom": {
|
|
95
|
+
"command": "phantom-mcp",
|
|
96
|
+
"env": {
|
|
97
|
+
"PHANTOM_APP_ID": "your_app_id_from_portal"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
After updating the config, restart Claude Desktop to load the server.
|
|
105
|
+
|
|
106
|
+
### Environment Variables
|
|
107
|
+
|
|
108
|
+
Configure the server behavior using environment variables:
|
|
109
|
+
|
|
110
|
+
**App ID / OAuth Client Credentials:**
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
PHANTOM_APP_ID=your_app_id # Required (App ID from Phantom Portal)
|
|
114
|
+
# OR
|
|
115
|
+
PHANTOM_CLIENT_ID=your_client_id # Alternative to PHANTOM_APP_ID
|
|
116
|
+
|
|
117
|
+
PHANTOM_CLIENT_SECRET=your_client_secret # Optional (for confidential clients)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Client Types:**
|
|
121
|
+
|
|
122
|
+
- **Public client** (recommended): Provide only `PHANTOM_APP_ID` (or `PHANTOM_CLIENT_ID`). Uses PKCE for security, similar to browser SDK.
|
|
123
|
+
- **Confidential client**: Provide both `PHANTOM_APP_ID` and `PHANTOM_CLIENT_SECRET`. Uses HTTP Basic Auth + PKCE.
|
|
124
|
+
|
|
125
|
+
**Note:** You must obtain your App ID from the [Phantom Portal](https://phantom.com/portal) before using the MCP server. See the "Getting Your App ID" section above for detailed instructions. Both `PHANTOM_APP_ID` and `PHANTOM_CLIENT_ID` are supported for backwards compatibility.
|
|
126
|
+
|
|
127
|
+
**Advanced Configuration (Optional):**
|
|
128
|
+
|
|
129
|
+
Most users won't need to change these settings. Available options:
|
|
130
|
+
|
|
131
|
+
- `PHANTOM_CALLBACK_PORT` - OAuth callback port (default: `8080`)
|
|
132
|
+
- `PHANTOM_CALLBACK_PATH` - OAuth callback path (default: `/callback`)
|
|
133
|
+
- `PHANTOM_MCP_DEBUG` - Enable debug logging (set to `1`)
|
|
134
|
+
|
|
135
|
+
**In Claude Desktop:**
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"mcpServers": {
|
|
140
|
+
"phantom": {
|
|
141
|
+
"command": "npx",
|
|
142
|
+
"args": ["-y", "@phantom/mcp-server"],
|
|
143
|
+
"env": {
|
|
144
|
+
"PHANTOM_APP_ID": "your_app_id_from_portal",
|
|
145
|
+
"PHANTOM_CLIENT_SECRET": "your_client_secret"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Authentication Flow
|
|
153
|
+
|
|
154
|
+
On first run, the server will:
|
|
155
|
+
|
|
156
|
+
1. **App ID**: Use App ID from `PHANTOM_APP_ID` (or `PHANTOM_CLIENT_ID`) environment variable
|
|
157
|
+
2. **Browser Authentication**: Open your default browser to `https://connect.phantom.app` for Google/Apple login
|
|
158
|
+
- **Important**: Use the same email address that you used to sign in to the Phantom Portal
|
|
159
|
+
3. **SSO Callback**: Start a local server on port 8080 to receive the SSO callback
|
|
160
|
+
4. **Session Storage**: Save your session (including wallet ID, organization ID, and stamper keys) to `~/.phantom-mcp/session.json`
|
|
161
|
+
|
|
162
|
+
The session file is secured with restrictive permissions (0o600) and contains:
|
|
163
|
+
|
|
164
|
+
- Wallet and organization identifiers
|
|
165
|
+
- Stamper keypair (public key registered with auth server, secret key for signing API requests)
|
|
166
|
+
- User authentication details
|
|
167
|
+
|
|
168
|
+
Sessions use stamper keys which don't expire. The embedded wallet is created during SSO authentication and persists across sessions.
|
|
169
|
+
|
|
170
|
+
### Manual Testing
|
|
171
|
+
|
|
172
|
+
Test the server directly using the MCP inspector:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npx @modelcontextprotocol/inspector npx -y @phantom/mcp-server
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
This opens an interactive web UI where you can test tool calls without Claude Desktop.
|
|
179
|
+
|
|
180
|
+
## Available Tools
|
|
181
|
+
|
|
182
|
+
### 1. get_wallet_addresses
|
|
183
|
+
|
|
184
|
+
Gets all blockchain addresses for the authenticated embedded wallet (Solana, Ethereum, Bitcoin, Sui).
|
|
185
|
+
|
|
186
|
+
**Parameters:**
|
|
187
|
+
|
|
188
|
+
- `derivationIndex` (optional, number): Derivation index for the addresses (default: 0)
|
|
189
|
+
|
|
190
|
+
**Example:**
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"derivationIndex": 0
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Response:**
|
|
199
|
+
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"walletId": "05307b6d-2d5a-43d6-8d11-08db650a169b",
|
|
203
|
+
"organizationId": "9b0ea123-5e7f-4dbe-88c5-7d769e2f8c8e",
|
|
204
|
+
"addresses": [
|
|
205
|
+
{
|
|
206
|
+
"addressType": "Solana",
|
|
207
|
+
"address": "H8FpYTgx4Uy9aF9Nk9fCTqKKFLYQ9KfC6UJhMkMDzCBh"
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"addressType": "Ethereum",
|
|
211
|
+
"address": "0x8d8b06e017944f5951418b1182d119a376efb39d"
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"addressType": "BitcoinSegwit",
|
|
215
|
+
"address": "bc1qkce5fvaxe759yu5xle5axlh8c7durjsx2wfhr9"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"addressType": "Sui",
|
|
219
|
+
"address": "0x039039cf69a336cb84e4c1dbcb3fa0c3f133d11b8146c6f7ed0d9f6817529a62"
|
|
220
|
+
}
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 2. sign_transaction
|
|
226
|
+
|
|
227
|
+
Signs a transaction using the authenticated embedded wallet. Supports Solana, Ethereum, Bitcoin, and other chains.
|
|
228
|
+
|
|
229
|
+
**Parameters:**
|
|
230
|
+
|
|
231
|
+
- `walletId` (optional, string): The wallet ID to use for signing (defaults to authenticated wallet)
|
|
232
|
+
- `transaction` (required, string): The transaction to sign (format depends on chain: base64url for Solana, RLP-encoded hex for Ethereum)
|
|
233
|
+
- `networkId` (required, string): Network identifier (e.g., "eip155:1" for Ethereum mainnet, "solana:mainnet" for Solana)
|
|
234
|
+
- `derivationIndex` (optional, number): Derivation index for the account (default: 0)
|
|
235
|
+
- `account` (optional, string): Specific account address to use for simulation/signing
|
|
236
|
+
|
|
237
|
+
**Example:**
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQABAgMEBQYH...",
|
|
242
|
+
"networkId": "solana:mainnet",
|
|
243
|
+
"derivationIndex": 0
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Response:**
|
|
248
|
+
|
|
249
|
+
```json
|
|
250
|
+
{
|
|
251
|
+
"signedTransaction": "base64url-encoded-signed-transaction"
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### 3. sign_message
|
|
256
|
+
|
|
257
|
+
Signs a UTF-8 message using the authenticated embedded wallet. Automatically routes to the correct signing method based on the network (Ethereum vs other chains).
|
|
258
|
+
|
|
259
|
+
**Parameters:**
|
|
260
|
+
|
|
261
|
+
- `walletId` (optional, string): The wallet ID to use for signing (defaults to authenticated wallet)
|
|
262
|
+
- `message` (required, string): The UTF-8 message to sign
|
|
263
|
+
- `networkId` (required, string): Network identifier (e.g., "eip155:1" for Ethereum mainnet, "solana:mainnet" for Solana)
|
|
264
|
+
- `derivationIndex` (optional, number): Derivation index for the account (default: 0)
|
|
265
|
+
|
|
266
|
+
**Example:**
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"message": "Hello, Phantom!",
|
|
271
|
+
"networkId": "solana:mainnet"
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Response:**
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"signature": "base64url-encoded-signature"
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Configuration
|
|
284
|
+
|
|
285
|
+
### Environment Variables
|
|
286
|
+
|
|
287
|
+
The MCP server supports the following environment variables:
|
|
288
|
+
|
|
289
|
+
#### Debug Logging
|
|
290
|
+
|
|
291
|
+
Enable debug logging to see detailed execution traces:
|
|
292
|
+
|
|
293
|
+
- `DEBUG=1` - Enable debug logging
|
|
294
|
+
- `PHANTOM_MCP_DEBUG=1` - Enable debug logging (alternative)
|
|
295
|
+
|
|
296
|
+
Debug logs are written to stderr and appear in Claude Desktop's MCP server logs.
|
|
297
|
+
|
|
298
|
+
### Session Storage
|
|
299
|
+
|
|
300
|
+
Sessions are stored in `~/.phantom-mcp/session.json` with the following security measures:
|
|
301
|
+
|
|
302
|
+
- Directory permissions: `0o700` (rwx for user only)
|
|
303
|
+
- File permissions: `0o600` (rw for user only)
|
|
304
|
+
- Contains: Wallet ID, organization ID, stamper keys, user authentication details
|
|
305
|
+
|
|
306
|
+
**Session persistence:**
|
|
307
|
+
|
|
308
|
+
- Sessions use stamper keypair authentication which doesn't expire
|
|
309
|
+
- Stamper public key is registered with the auth server during SSO
|
|
310
|
+
- Stamper secret key is used to sign all API requests
|
|
311
|
+
- Sessions persist indefinitely until explicitly deleted
|
|
312
|
+
|
|
313
|
+
**To reset your session:**
|
|
314
|
+
|
|
315
|
+
1. Delete the session file:
|
|
316
|
+
```bash
|
|
317
|
+
rm ~/.phantom-mcp/session.json
|
|
318
|
+
```
|
|
319
|
+
2. Restart Claude Desktop (the server will re-authenticate on next use)
|
|
320
|
+
|
|
321
|
+
## Security
|
|
322
|
+
|
|
323
|
+
### OAuth Flow Security
|
|
324
|
+
|
|
325
|
+
- Uses PKCE (Proof Key for Code Exchange) for secure OAuth authentication
|
|
326
|
+
- App IDs are pre-registered through the Phantom Portal
|
|
327
|
+
- Session ID validation prevents replay attacks
|
|
328
|
+
- Callback server uses ephemeral localhost binding
|
|
329
|
+
|
|
330
|
+
### Session Security
|
|
331
|
+
|
|
332
|
+
- Session files have restrictive Unix permissions (user-only read/write)
|
|
333
|
+
- API keys are generated using cryptographically secure random sources
|
|
334
|
+
- Tokens are encrypted in transit (HTTPS)
|
|
335
|
+
- No plaintext credentials are stored
|
|
336
|
+
|
|
337
|
+
### Network Security
|
|
338
|
+
|
|
339
|
+
- All API requests use HTTPS
|
|
340
|
+
- Request signing with API key stamper prevents tampering
|
|
341
|
+
- Session tokens are bearer tokens with limited scope
|
|
342
|
+
|
|
343
|
+
## Troubleshooting
|
|
344
|
+
|
|
345
|
+
### Browser Doesn't Open
|
|
346
|
+
|
|
347
|
+
**Problem:** The OAuth flow tries to open your browser but fails.
|
|
348
|
+
|
|
349
|
+
**Solutions:**
|
|
350
|
+
|
|
351
|
+
- Ensure you have a default browser configured
|
|
352
|
+
- Manually visit the URL shown in the logs
|
|
353
|
+
- Check if the `open` command works in your terminal: `open https://phantom.app`
|
|
354
|
+
|
|
355
|
+
### Port 8080 Already in Use
|
|
356
|
+
|
|
357
|
+
**Problem:** Cannot bind OAuth callback server to port 8080.
|
|
358
|
+
|
|
359
|
+
**Error:** `EADDRINUSE: address already in use :::8080`
|
|
360
|
+
|
|
361
|
+
**Solutions:**
|
|
362
|
+
|
|
363
|
+
- Stop the process using port 8080: `lsof -ti:8080 | xargs kill`
|
|
364
|
+
- Change the callback port: Set `PHANTOM_CALLBACK_PORT` environment variable to a different port
|
|
365
|
+
|
|
366
|
+
### Authentication Email Mismatch
|
|
367
|
+
|
|
368
|
+
**Problem:** Authentication fails or you can't access your wallet.
|
|
369
|
+
|
|
370
|
+
**Solution:** Ensure you're using the **same email address** for both:
|
|
371
|
+
|
|
372
|
+
- Signing in to the Phantom Portal (where you created your app)
|
|
373
|
+
- Authenticating in the MCP server (Google/Apple login)
|
|
374
|
+
|
|
375
|
+
If the emails don't match, authentication will fail.
|
|
376
|
+
|
|
377
|
+
### Session Not Persisting
|
|
378
|
+
|
|
379
|
+
**Problem:** The server asks you to authenticate every time.
|
|
380
|
+
|
|
381
|
+
**Solutions:**
|
|
382
|
+
|
|
383
|
+
- Check session file exists: `ls -la ~/.phantom-mcp/session.json`
|
|
384
|
+
- Verify file permissions: `chmod 600 ~/.phantom-mcp/session.json`
|
|
385
|
+
- Check logs for session expiry messages
|
|
386
|
+
- Ensure `~/.phantom-mcp` directory has correct permissions: `chmod 700 ~/.phantom-mcp`
|
|
387
|
+
|
|
388
|
+
### MCP Server Not Loading in Claude
|
|
389
|
+
|
|
390
|
+
**Problem:** Claude Desktop doesn't show the Phantom tools.
|
|
391
|
+
|
|
392
|
+
**Solutions:**
|
|
393
|
+
|
|
394
|
+
1. Verify config file syntax is valid JSON
|
|
395
|
+
2. Check Claude Desktop logs:
|
|
396
|
+
- macOS: `~/Library/Logs/Claude/`
|
|
397
|
+
- Windows: `%APPDATA%/Claude/logs/`
|
|
398
|
+
3. Restart Claude Desktop after config changes
|
|
399
|
+
4. Test the server manually with MCP inspector (see Manual Testing section)
|
|
400
|
+
|
|
401
|
+
### Authentication Timeout
|
|
402
|
+
|
|
403
|
+
**Problem:** Authentication flow times out before you complete it.
|
|
404
|
+
|
|
405
|
+
**Solutions:**
|
|
406
|
+
|
|
407
|
+
- The OAuth callback server waits 5 minutes by default
|
|
408
|
+
- Complete the authentication flow promptly
|
|
409
|
+
- If timeout occurs, restart Claude Desktop to retry
|
|
410
|
+
|
|
411
|
+
### Invalid Session Error
|
|
412
|
+
|
|
413
|
+
**Problem:** Session exists but is rejected by API.
|
|
414
|
+
|
|
415
|
+
**Solutions:**
|
|
416
|
+
|
|
417
|
+
- Verify your App ID is correct (check the Phantom Portal)
|
|
418
|
+
- Ensure the email used for authentication matches the Portal email
|
|
419
|
+
- Delete session file: `rm ~/.phantom-mcp/session.json`
|
|
420
|
+
- Restart Claude Desktop
|
|
421
|
+
- Re-authenticate when prompted
|
|
422
|
+
|
|
423
|
+
## Development
|
|
424
|
+
|
|
425
|
+
### Prerequisites
|
|
426
|
+
|
|
427
|
+
- Node.js 18+ and yarn
|
|
428
|
+
- TypeScript 5+
|
|
429
|
+
|
|
430
|
+
### Building
|
|
431
|
+
|
|
432
|
+
```bash
|
|
433
|
+
# Install dependencies
|
|
434
|
+
yarn install
|
|
435
|
+
|
|
436
|
+
# Build the project
|
|
437
|
+
yarn build
|
|
438
|
+
|
|
439
|
+
# Watch mode for development
|
|
440
|
+
yarn dev
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Testing
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
# Run all tests
|
|
447
|
+
yarn test
|
|
448
|
+
|
|
449
|
+
# Watch mode
|
|
450
|
+
yarn test:watch
|
|
451
|
+
|
|
452
|
+
# Check types
|
|
453
|
+
yarn check-types
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Linting
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
# Run ESLint
|
|
460
|
+
yarn lint
|
|
461
|
+
|
|
462
|
+
# Format code with Prettier
|
|
463
|
+
yarn prettier
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### Running Locally
|
|
467
|
+
|
|
468
|
+
You can test the MCP server locally before installing:
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
# Build first
|
|
472
|
+
yarn build
|
|
473
|
+
|
|
474
|
+
# Run directly
|
|
475
|
+
node dist/index.js
|
|
476
|
+
|
|
477
|
+
# Or using the bin wrapper
|
|
478
|
+
./bin/phantom-mcp
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
## Contributing
|
|
482
|
+
|
|
483
|
+
This package is part of the [Phantom Connect SDK](https://github.com/phantom/phantom-connect-sdk) monorepo. Please refer to the main repository for contribution guidelines.
|
|
484
|
+
|
|
485
|
+
## License
|
|
486
|
+
|
|
487
|
+
See the main repository [LICENSE](../../LICENSE) file.
|
|
488
|
+
|
|
489
|
+
## Support
|
|
490
|
+
|
|
491
|
+
- [Phantom Documentation](https://docs.phantom.com)
|
|
492
|
+
- [GitHub Issues](https://github.com/phantom/phantom-connect-sdk/issues)
|
|
493
|
+
|
|
494
|
+
## Related Packages
|
|
495
|
+
|
|
496
|
+
- [@phantom/server-sdk](../server-sdk) - Server-side SDK for Phantom integration
|
|
497
|
+
- [@phantom/client](../client) - Client library for Phantom API
|
|
498
|
+
- [@phantom/react-sdk](../react-sdk) - React SDK for browser applications
|
package/bin/phantom-mcp
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { PhantomClient } from '@phantom/client';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Complete session data stored on disk
|
|
6
|
+
*
|
|
7
|
+
* Note: SSO flow uses stamper keys for API authentication, not OAuth tokens
|
|
8
|
+
*/
|
|
9
|
+
interface SessionData {
|
|
10
|
+
walletId: string;
|
|
11
|
+
organizationId: string;
|
|
12
|
+
authUserId: string;
|
|
13
|
+
stamperKeys: {
|
|
14
|
+
publicKey: string;
|
|
15
|
+
secretKey: string;
|
|
16
|
+
};
|
|
17
|
+
createdAt: number;
|
|
18
|
+
updatedAt: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* SessionManager orchestrates the complete session lifecycle:
|
|
23
|
+
* - Loads existing sessions from storage
|
|
24
|
+
* - Handles authentication when needed
|
|
25
|
+
* - Creates and manages PhantomClient instances
|
|
26
|
+
* - Provides session data access
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Configuration options for SessionManager
|
|
31
|
+
*/
|
|
32
|
+
interface SessionManagerOptions {
|
|
33
|
+
/** Base URL for OAuth authorization server (default: https://auth.phantom.app or PHANTOM_AUTH_BASE_URL env var) */
|
|
34
|
+
authBaseUrl?: string;
|
|
35
|
+
/** Base URL for Phantom Connect (default: https://connect.phantom.app or PHANTOM_CONNECT_BASE_URL env var) */
|
|
36
|
+
connectBaseUrl?: string;
|
|
37
|
+
/** Base URL for Phantom API (default: https://api.phantom.app or PHANTOM_API_BASE_URL env var) */
|
|
38
|
+
apiBaseUrl?: string;
|
|
39
|
+
/** Port for local OAuth callback server (default: 8080 or PHANTOM_CALLBACK_PORT env var) */
|
|
40
|
+
callbackPort?: number;
|
|
41
|
+
/** Path for OAuth callback (default: /callback or PHANTOM_CALLBACK_PATH env var) */
|
|
42
|
+
callbackPath?: string;
|
|
43
|
+
/** Application identifier prefix (default: phantom-mcp) */
|
|
44
|
+
appId?: string;
|
|
45
|
+
/** Directory to store session data (default: ~/.phantom-mcp) */
|
|
46
|
+
sessionDir?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* SessionManager handles session lifecycle, auto-authentication, and PhantomClient creation
|
|
50
|
+
*
|
|
51
|
+
* Usage:
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const manager = new SessionManager();
|
|
54
|
+
* await manager.initialize(); // Loads session or authenticates
|
|
55
|
+
* const client = manager.getClient();
|
|
56
|
+
* const session = manager.getSession();
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
declare class SessionManager {
|
|
60
|
+
private readonly authBaseUrl;
|
|
61
|
+
private readonly connectBaseUrl?;
|
|
62
|
+
private readonly apiBaseUrl;
|
|
63
|
+
private readonly callbackPort;
|
|
64
|
+
private readonly callbackPath;
|
|
65
|
+
private readonly appId;
|
|
66
|
+
private readonly storage;
|
|
67
|
+
private readonly logger;
|
|
68
|
+
private session;
|
|
69
|
+
private client;
|
|
70
|
+
/**
|
|
71
|
+
* Creates a new SessionManager
|
|
72
|
+
*
|
|
73
|
+
* @param options - Configuration options
|
|
74
|
+
*/
|
|
75
|
+
constructor(options?: SessionManagerOptions);
|
|
76
|
+
/**
|
|
77
|
+
* Initializes the session manager
|
|
78
|
+
* Loads existing session or authenticates if needed
|
|
79
|
+
*
|
|
80
|
+
* @throws Error if authentication fails
|
|
81
|
+
*/
|
|
82
|
+
initialize(): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Returns the initialized PhantomClient
|
|
85
|
+
*
|
|
86
|
+
* @returns PhantomClient instance
|
|
87
|
+
* @throws Error if not initialized
|
|
88
|
+
*/
|
|
89
|
+
getClient(): PhantomClient;
|
|
90
|
+
/**
|
|
91
|
+
* Returns the current session data
|
|
92
|
+
*
|
|
93
|
+
* @returns Current session data
|
|
94
|
+
* @throws Error if not initialized
|
|
95
|
+
*/
|
|
96
|
+
getSession(): SessionData;
|
|
97
|
+
/**
|
|
98
|
+
* Resets the session by clearing stored data and re-authenticating
|
|
99
|
+
*
|
|
100
|
+
* @throws Error if authentication fails
|
|
101
|
+
*/
|
|
102
|
+
resetSession(): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Executes the SSO flow and creates a new session
|
|
105
|
+
* Steps:
|
|
106
|
+
* 1. Execute SSO flow to get wallet/org IDs and stamper keypair
|
|
107
|
+
* 2. Create SessionData with SSO result and stamper keys
|
|
108
|
+
* 3. Save to storage
|
|
109
|
+
* 4. Create PhantomClient
|
|
110
|
+
*
|
|
111
|
+
* Note: Stamper keypair is generated during SSO flow and public key is sent to auth server
|
|
112
|
+
*
|
|
113
|
+
* @throws Error if SSO flow fails
|
|
114
|
+
*/
|
|
115
|
+
private authenticate;
|
|
116
|
+
/**
|
|
117
|
+
* Creates a PhantomClient instance from the current session
|
|
118
|
+
* Steps:
|
|
119
|
+
* 1. Create ApiKeyStamper with session keypair
|
|
120
|
+
* 2. Create PhantomClient with stamper, organizationId, and app headers
|
|
121
|
+
* 3. Set walletType to 'user-wallet'
|
|
122
|
+
*
|
|
123
|
+
* @throws Error if session is not available
|
|
124
|
+
*/
|
|
125
|
+
private createClient;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export { SessionManager };
|