@suisei-mcp/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/README.md +199 -0
- package/dist/coins.d.ts +21 -0
- package/dist/coins.js +59 -0
- package/dist/coins.js.map +1 -0
- package/dist/deepbook.d.ts +20 -0
- package/dist/deepbook.js +63 -0
- package/dist/deepbook.js.map +1 -0
- package/dist/http.d.ts +24 -0
- package/dist/http.js +42 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.ts +12 -0
- package/dist/node.js +54 -0
- package/dist/node.js.map +1 -0
- package/dist/serve.d.ts +13 -0
- package/dist/serve.js +25 -0
- package/dist/serve.js.map +1 -0
- package/dist/server.d.ts +20 -0
- package/dist/server.js +569 -0
- package/dist/server.js.map +1 -0
- package/dist/sui-client.d.ts +16 -0
- package/dist/sui-client.js +64 -0
- package/dist/sui-client.js.map +1 -0
- package/dist/tools/agent_wallet_fund.d.ts +11 -0
- package/dist/tools/agent_wallet_fund.js +31 -0
- package/dist/tools/agent_wallet_fund.js.map +1 -0
- package/dist/tools/agent_wallet_status.d.ts +6 -0
- package/dist/tools/agent_wallet_status.js +22 -0
- package/dist/tools/agent_wallet_status.js.map +1 -0
- package/dist/tools/agent_wallet_sweep.d.ts +11 -0
- package/dist/tools/agent_wallet_sweep.js +34 -0
- package/dist/tools/agent_wallet_sweep.js.map +1 -0
- package/dist/tools/sui_decode_tx_bytes.d.ts +15 -0
- package/dist/tools/sui_decode_tx_bytes.js +140 -0
- package/dist/tools/sui_decode_tx_bytes.js.map +1 -0
- package/dist/tools/sui_deepbook_quote.d.ts +12 -0
- package/dist/tools/sui_deepbook_quote.js +72 -0
- package/dist/tools/sui_deepbook_quote.js.map +1 -0
- package/dist/tools/sui_deepbook_swap.d.ts +15 -0
- package/dist/tools/sui_deepbook_swap.js +72 -0
- package/dist/tools/sui_deepbook_swap.js.map +1 -0
- package/dist/tools/sui_dry_run.d.ts +6 -0
- package/dist/tools/sui_dry_run.js +24 -0
- package/dist/tools/sui_dry_run.js.map +1 -0
- package/dist/tools/sui_execute_signed_tx.d.ts +6 -0
- package/dist/tools/sui_execute_signed_tx.js +25 -0
- package/dist/tools/sui_execute_signed_tx.js.map +1 -0
- package/dist/tools/sui_get_all_balances.d.ts +5 -0
- package/dist/tools/sui_get_all_balances.js +21 -0
- package/dist/tools/sui_get_all_balances.js.map +1 -0
- package/dist/tools/sui_get_balance.d.ts +1 -0
- package/dist/tools/sui_get_balance.js +17 -0
- package/dist/tools/sui_get_balance.js.map +1 -0
- package/dist/tools/sui_get_coin_metadata.d.ts +10 -0
- package/dist/tools/sui_get_coin_metadata.js +38 -0
- package/dist/tools/sui_get_coin_metadata.js.map +1 -0
- package/dist/tools/sui_get_coins.d.ts +6 -0
- package/dist/tools/sui_get_coins.js +31 -0
- package/dist/tools/sui_get_coins.js.map +1 -0
- package/dist/tools/sui_get_dynamic_fields.d.ts +6 -0
- package/dist/tools/sui_get_dynamic_fields.js +30 -0
- package/dist/tools/sui_get_dynamic_fields.js.map +1 -0
- package/dist/tools/sui_get_object.d.ts +5 -0
- package/dist/tools/sui_get_object.js +37 -0
- package/dist/tools/sui_get_object.js.map +1 -0
- package/dist/tools/sui_get_owned_badges.d.ts +1 -0
- package/dist/tools/sui_get_owned_badges.js +64 -0
- package/dist/tools/sui_get_owned_badges.js.map +1 -0
- package/dist/tools/sui_get_owned_objects.d.ts +5 -0
- package/dist/tools/sui_get_owned_objects.js +32 -0
- package/dist/tools/sui_get_owned_objects.js.map +1 -0
- package/dist/tools/sui_get_reference_gas_price.d.ts +5 -0
- package/dist/tools/sui_get_reference_gas_price.js +15 -0
- package/dist/tools/sui_get_reference_gas_price.js.map +1 -0
- package/dist/tools/sui_get_stakes.d.ts +11 -0
- package/dist/tools/sui_get_stakes.js +54 -0
- package/dist/tools/sui_get_stakes.js.map +1 -0
- package/dist/tools/sui_get_transaction.d.ts +6 -0
- package/dist/tools/sui_get_transaction.js +26 -0
- package/dist/tools/sui_get_transaction.js.map +1 -0
- package/dist/tools/sui_get_validator.d.ts +8 -0
- package/dist/tools/sui_get_validator.js +43 -0
- package/dist/tools/sui_get_validator.js.map +1 -0
- package/dist/tools/sui_get_validators.d.ts +9 -0
- package/dist/tools/sui_get_validators.js +46 -0
- package/dist/tools/sui_get_validators.js.map +1 -0
- package/dist/tools/sui_get_validators_apy.d.ts +10 -0
- package/dist/tools/sui_get_validators_apy.js +37 -0
- package/dist/tools/sui_get_validators_apy.js.map +1 -0
- package/dist/tools/sui_mint_badge.d.ts +7 -0
- package/dist/tools/sui_mint_badge.js +35 -0
- package/dist/tools/sui_mint_badge.js.map +1 -0
- package/dist/tools/sui_move_call.d.ts +18 -0
- package/dist/tools/sui_move_call.js +88 -0
- package/dist/tools/sui_move_call.js.map +1 -0
- package/dist/tools/sui_pay_many.d.ts +10 -0
- package/dist/tools/sui_pay_many.js +40 -0
- package/dist/tools/sui_pay_many.js.map +1 -0
- package/dist/tools/sui_query_events.d.ts +12 -0
- package/dist/tools/sui_query_events.js +59 -0
- package/dist/tools/sui_query_events.js.map +1 -0
- package/dist/tools/sui_resolve_address.d.ts +6 -0
- package/dist/tools/sui_resolve_address.js +22 -0
- package/dist/tools/sui_resolve_address.js.map +1 -0
- package/dist/tools/sui_resolve_coin.d.ts +9 -0
- package/dist/tools/sui_resolve_coin.js +26 -0
- package/dist/tools/sui_resolve_coin.js.map +1 -0
- package/dist/tools/sui_stake.d.ts +6 -0
- package/dist/tools/sui_stake.js +29 -0
- package/dist/tools/sui_stake.js.map +1 -0
- package/dist/tools/sui_transfer.d.ts +5 -0
- package/dist/tools/sui_transfer.js +34 -0
- package/dist/tools/sui_transfer.js.map +1 -0
- package/dist/tools/sui_unstake.d.ts +6 -0
- package/dist/tools/sui_unstake.js +27 -0
- package/dist/tools/sui_unstake.js.map +1 -0
- package/dist/tools/walrus_fetch.d.ts +1 -0
- package/dist/tools/walrus_fetch.js +18 -0
- package/dist/tools/walrus_fetch.js.map +1 -0
- package/dist/tools/walrus_publish.d.ts +1 -0
- package/dist/tools/walrus_publish.js +42 -0
- package/dist/tools/walrus_publish.js.map +1 -0
- package/dist/tx.d.ts +12 -0
- package/dist/tx.js +18 -0
- package/dist/tx.js.map +1 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# @suisei-mcp/mcp — Suisei MCP
|
|
2
|
+
|
|
3
|
+
The Sui Stack as one-line tools, exposed over the Model Context Protocol
|
|
4
|
+
— so any MCP-aware client (Claude Desktop, Cursor, Windsurf, your own
|
|
5
|
+
agent) can build on Sui. The server identifies itself as **Suisei** to
|
|
6
|
+
the agent. Tool names keep the `sui_` prefix because they wrap the Sui
|
|
7
|
+
chain — Suisei is the agent toolkit; Sui is the chain it speaks.
|
|
8
|
+
[Suisei the teaching agent](https://suisei.dev) is a showcase built
|
|
9
|
+
entirely on these tools.
|
|
10
|
+
|
|
11
|
+
> **Status:** Alpha. Thirty-three tools spanning the core build loop —
|
|
12
|
+
> read chain state, build any transaction, simulate it, decode it,
|
|
13
|
+
> submit it — plus native staking (stake, unstake, live APY, validator
|
|
14
|
+
> set, position tracking), DeepBook quotes & swaps, batch payouts,
|
|
15
|
+
> historical events, coin metadata + symbol registry, Tier-1
|
|
16
|
+
> agent-wallet lifecycle, and Walrus storage. Next up: the on-chain
|
|
17
|
+
> policy vault and Seal.
|
|
18
|
+
|
|
19
|
+
## Why
|
|
20
|
+
|
|
21
|
+
Most Sui SDKs assume you're writing application code. This package
|
|
22
|
+
assumes you're writing **agent** code — short tool calls, structured
|
|
23
|
+
JSON in, structured JSON out, no React, no UI. The agent decides what
|
|
24
|
+
to do; the tool does it.
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install -g @suisei-mcp/mcp
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Use with Claude Desktop
|
|
33
|
+
|
|
34
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
35
|
+
(macOS) or the equivalent on your platform:
|
|
36
|
+
|
|
37
|
+
```jsonc
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"suisei": {
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": ["-y", "@suisei-mcp/mcp"]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Restart Claude Desktop. You can now ask the agent things like:
|
|
49
|
+
|
|
50
|
+
> "What's the balance of `alice.sui`?"
|
|
51
|
+
> "Mint a badge to `0x1234…` for completing the zkLogin quest."
|
|
52
|
+
> "Publish this paragraph to Walrus and give me the blob id."
|
|
53
|
+
|
|
54
|
+
The agent picks the right tool. You see the result.
|
|
55
|
+
|
|
56
|
+
## Use it remotely (Claude web + mobile)
|
|
57
|
+
|
|
58
|
+
Stdio only works where the host can spawn a local process (Claude
|
|
59
|
+
Desktop, Cursor). To use the toolkit from the **Claude web and mobile
|
|
60
|
+
apps**, run it as a **remote MCP server** and add the URL as a Custom
|
|
61
|
+
Connector (Settings → Connectors).
|
|
62
|
+
|
|
63
|
+
Host it anywhere with the bundled HTTP server:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
PORT=8787 SUISEI_MCP_TOKEN=your-secret npx suisei-mcp-serve
|
|
67
|
+
# serves Streamable HTTP at http://localhost:8787/ (front with HTTPS in prod)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
On serverless, import the runtime-agnostic Fetch handler directly — it
|
|
71
|
+
runs on Vercel Edge, Cloudflare Workers, Deno, and Bun:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
// api/mcp.ts (Vercel Edge) — needs `@suisei-mcp/mcp` as a dependency
|
|
75
|
+
export const config = { runtime: 'edge' };
|
|
76
|
+
import { handleMcpRequest } from '@suisei-mcp/mcp/http';
|
|
77
|
+
export default (req: Request) => handleMcpRequest(req);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Set `SUISEI_MCP_TOKEN` so the endpoint requires
|
|
81
|
+
`Authorization: Bearer <token>` — a public MCP URL without a token is
|
|
82
|
+
open to the world.
|
|
83
|
+
|
|
84
|
+
**Signing caveat.** Reads (balances, coins, objects, transactions,
|
|
85
|
+
dynamic fields, gas, Walrus) work over a remote connector immediately.
|
|
86
|
+
The transaction-building tools still return *unsigned* bytes — signing
|
|
87
|
+
happens host-side, and a remote host (mobile) has no local wallet, so it
|
|
88
|
+
needs its own signing path (e.g. an Enoki-sponsored flow or a wallet
|
|
89
|
+
deep-link) to submit.
|
|
90
|
+
|
|
91
|
+
## Tools
|
|
92
|
+
|
|
93
|
+
**Read the chain**
|
|
94
|
+
|
|
95
|
+
| Tool | What it does |
|
|
96
|
+
| ----------------------- | ------------------------------------------------------------ |
|
|
97
|
+
| `sui_resolve_address` | SuiNS name → 0x address (idempotent on 0x inputs) |
|
|
98
|
+
| `sui_get_balance` | SUI balance (in MIST + human-readable SUI) |
|
|
99
|
+
| `sui_get_all_balances` | Every coin balance a wallet holds, not just SUI |
|
|
100
|
+
| `sui_get_object` | Any object's type, owner, fields, and Display |
|
|
101
|
+
| `sui_get_owned_objects` | List objects by owner, filterable by struct type, paginated |
|
|
102
|
+
| `sui_get_owned_badges` | List a wallet's Suisei completion badges |
|
|
103
|
+
| `sui_get_coins` | List coin objects of a type (the ids you spend), paginated |
|
|
104
|
+
| `sui_get_transaction` | Look up a finalized tx by digest: status, gas, changes |
|
|
105
|
+
| `sui_get_reference_gas_price` | Current network reference gas price (MIST) |
|
|
106
|
+
| `sui_get_dynamic_fields` | List an object's dynamic fields (Tables, Bags), paginated |
|
|
107
|
+
| `sui_get_stakes` | A wallet's active stakes: principal, accrued rewards, ids |
|
|
108
|
+
| `sui_get_validators_apy` | Live APY per validator (the APR feed for staking) |
|
|
109
|
+
| `sui_get_validators` | Active validator set: name, address, commission, total stake |
|
|
110
|
+
| `sui_get_validator` | One validator, with APY + commission + stake merged |
|
|
111
|
+
| `sui_query_events` | Historical events: filter by type / module / sender / tx |
|
|
112
|
+
| `sui_get_coin_metadata` | Live coin metadata (symbol, decimals, name, icon URL) |
|
|
113
|
+
| `sui_resolve_coin` | Symbol → coin type from a built-in registry (USDC, DEEP, …) |
|
|
114
|
+
| `sui_deepbook_quote` | Read-only DeepBook v3 quote: expected out + DEEP fee |
|
|
115
|
+
| `agent_wallet_status` | An agent wallet's SUI balance + whether it's funded |
|
|
116
|
+
|
|
117
|
+
**Build a transaction (never signed — bytes returned for the host)**
|
|
118
|
+
|
|
119
|
+
| Tool | What it does |
|
|
120
|
+
| ----------------------- | ------------------------------------------------------------ |
|
|
121
|
+
| `sui_move_call` | Build a call to ANY Move entry function — the universal write |
|
|
122
|
+
| `sui_transfer` | Build a transfer of SUI and/or whole objects |
|
|
123
|
+
| `sui_pay_many` | Build a batch payout: N recipients, N amounts, one atomic tx |
|
|
124
|
+
| `sui_stake` | Build a native staking delegation to a validator |
|
|
125
|
+
| `sui_unstake` | Build a withdraw-stake for a StakedSui object |
|
|
126
|
+
| `sui_mint_badge` | Build a Suisei completion-badge mint |
|
|
127
|
+
| `sui_deepbook_swap` | Build a DeepBook v3 market swap (CLOB liquidity) |
|
|
128
|
+
| `agent_wallet_fund` | Owner-signed: top up an agent wallet's allowance |
|
|
129
|
+
| `agent_wallet_sweep` | Agent-signed kill switch: drain the wallet back to the owner |
|
|
130
|
+
|
|
131
|
+
**Simulate & submit**
|
|
132
|
+
|
|
133
|
+
| Tool | What it does |
|
|
134
|
+
| ----------------------- | ------------------------------------------------------------ |
|
|
135
|
+
| `sui_dry_run` | Simulate built tx bytes (status + gas, no spend) |
|
|
136
|
+
| `sui_decode_tx_bytes` | Offline decode: turn unsigned bytes into a human-readable plan |
|
|
137
|
+
| `sui_execute_signed_tx` | Submit host-signed tx bytes, return digest + effects |
|
|
138
|
+
|
|
139
|
+
**Walrus storage**
|
|
140
|
+
|
|
141
|
+
| Tool | What it does |
|
|
142
|
+
| ----------------------- | ------------------------------------------------------------ |
|
|
143
|
+
| `walrus_publish` | Publish a blob to Walrus testnet/mainnet |
|
|
144
|
+
| `walrus_fetch` | Fetch a blob from Walrus by id |
|
|
145
|
+
|
|
146
|
+
The build loop is: a `*_build`-style tool returns base64 tx bytes →
|
|
147
|
+
`sui_dry_run` to verify → the host signs → `sui_execute_signed_tx` to
|
|
148
|
+
submit. The toolkit never holds keys.
|
|
149
|
+
|
|
150
|
+
All tools return structured JSON in the `text` content block. The
|
|
151
|
+
calling agent is expected to parse it.
|
|
152
|
+
|
|
153
|
+
## Design rules
|
|
154
|
+
|
|
155
|
+
- **No private keys.** Tools that produce transactions return tx bytes;
|
|
156
|
+
the host signs and submits. A tool that holds a key is a tool that
|
|
157
|
+
can spend money.
|
|
158
|
+
- **One job per tool.** No mega-tools with twelve flags. The agent's
|
|
159
|
+
reasoning gets sharper when each tool is unambiguous.
|
|
160
|
+
- **Structured output.** Every successful return is JSON. The agent
|
|
161
|
+
reads structured data more accurately than prose.
|
|
162
|
+
|
|
163
|
+
## Transport & deprecation
|
|
164
|
+
|
|
165
|
+
Sui is deprecating public JSON-RPC fullnode endpoints (~mid-2026) in
|
|
166
|
+
favour of gRPC and GraphQL. Transport is chosen in one place —
|
|
167
|
+
`src/sui-client.ts` — so the rest of the toolkit never imports a client
|
|
168
|
+
directly.
|
|
169
|
+
|
|
170
|
+
Today `clientFor()` returns the JSON-RPC client, because building a
|
|
171
|
+
transaction (`tx.build({ client })`) needs *transaction resolution*,
|
|
172
|
+
which `@mysten/sui` 1.45.x implements only for JSON-RPC. Verified against
|
|
173
|
+
testnet: both the gRPC and GraphQL clients reject `tx.build` ("not
|
|
174
|
+
supported"/"not supported yet"). Reads already work over gRPC via
|
|
175
|
+
`grpcClientFor()`, also in that file.
|
|
176
|
+
|
|
177
|
+
When the SDK ships transaction-building over gRPC, the cutover is a
|
|
178
|
+
one-line change in `clientFor()` — no tool touches transport directly.
|
|
179
|
+
|
|
180
|
+
## Development
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
git clone https://github.com/eienel/blockbuilders
|
|
184
|
+
cd blockbuilders/packages/mcp
|
|
185
|
+
npm install
|
|
186
|
+
npm run build
|
|
187
|
+
node dist/index.js
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The server speaks JSON-RPC 2.0 over stdio per the MCP spec. To test
|
|
191
|
+
without an agent, you can pipe a handshake in by hand:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | node dist/index.js
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT.
|
package/dist/coins.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Network } from './sui-client.js';
|
|
2
|
+
/**
|
|
3
|
+
* Coin metadata registry — the "what is USDC's coin type" table. Static
|
|
4
|
+
* because mainnet/testnet coin types are upgrade-stable; if Sui ever
|
|
5
|
+
* redeploys one, override the type explicitly in any tool that takes
|
|
6
|
+
* coin_type, or update this file. Decimals are cached here so an agent
|
|
7
|
+
* can size amounts without an extra RPC call, but sui_get_coin_metadata
|
|
8
|
+
* is the authoritative live lookup.
|
|
9
|
+
*/
|
|
10
|
+
export interface CoinInfo {
|
|
11
|
+
symbol: string;
|
|
12
|
+
coin_type: string;
|
|
13
|
+
decimals: number;
|
|
14
|
+
description?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Common coins by symbol (case-insensitive lookup). */
|
|
17
|
+
export declare const COINS: Record<Network, Record<string, CoinInfo>>;
|
|
18
|
+
/** Look up a coin by symbol on a network. Case-insensitive. */
|
|
19
|
+
export declare function findCoin(network: Network, symbol: string): CoinInfo | undefined;
|
|
20
|
+
/** List known coin symbols for a network. */
|
|
21
|
+
export declare function knownSymbols(network: Network): string[];
|
package/dist/coins.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const SUI = '0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI';
|
|
2
|
+
/** Common coins by symbol (case-insensitive lookup). */
|
|
3
|
+
export const COINS = {
|
|
4
|
+
testnet: {
|
|
5
|
+
SUI: { symbol: 'SUI', coin_type: SUI, decimals: 9, description: 'Native Sui coin.' },
|
|
6
|
+
DBUSDC: {
|
|
7
|
+
symbol: 'DBUSDC',
|
|
8
|
+
coin_type: '0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7::DBUSDC::DBUSDC',
|
|
9
|
+
decimals: 6,
|
|
10
|
+
description: 'DeepBook test USDC (testnet).',
|
|
11
|
+
},
|
|
12
|
+
DEEP: {
|
|
13
|
+
symbol: 'DEEP',
|
|
14
|
+
coin_type: '0x36dbef866a1d62bf7328989a10fb2f07d769f4ee587c0de4a0a256e57e0a58a8::deep::DEEP',
|
|
15
|
+
decimals: 6,
|
|
16
|
+
description: 'DeepBook utility token (testnet).',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
mainnet: {
|
|
20
|
+
SUI: { symbol: 'SUI', coin_type: SUI, decimals: 9, description: 'Native Sui coin.' },
|
|
21
|
+
USDC: {
|
|
22
|
+
symbol: 'USDC',
|
|
23
|
+
coin_type: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',
|
|
24
|
+
decimals: 6,
|
|
25
|
+
description: 'Native USDC on Sui (Circle).',
|
|
26
|
+
},
|
|
27
|
+
USDT: {
|
|
28
|
+
symbol: 'USDT',
|
|
29
|
+
coin_type: '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN',
|
|
30
|
+
decimals: 6,
|
|
31
|
+
description: 'Wormhole USDT (canonical bridged).',
|
|
32
|
+
},
|
|
33
|
+
DEEP: {
|
|
34
|
+
symbol: 'DEEP',
|
|
35
|
+
coin_type: '0xdeeb7a4662eec9f2f3def03fb937a663dddaa2e215b8078a284d026b7946c270::deep::DEEP',
|
|
36
|
+
decimals: 6,
|
|
37
|
+
description: 'DeepBook utility token.',
|
|
38
|
+
},
|
|
39
|
+
WAL: {
|
|
40
|
+
symbol: 'WAL',
|
|
41
|
+
coin_type: '0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL',
|
|
42
|
+
decimals: 9,
|
|
43
|
+
description: 'Walrus native token.',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
devnet: {
|
|
47
|
+
SUI: { symbol: 'SUI', coin_type: SUI, decimals: 9, description: 'Native Sui coin.' },
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
/** Look up a coin by symbol on a network. Case-insensitive. */
|
|
51
|
+
export function findCoin(network, symbol) {
|
|
52
|
+
const table = COINS[network] ?? {};
|
|
53
|
+
return table[symbol.toUpperCase()];
|
|
54
|
+
}
|
|
55
|
+
/** List known coin symbols for a network. */
|
|
56
|
+
export function knownSymbols(network) {
|
|
57
|
+
return Object.keys(COINS[network] ?? {});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=coins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coins.js","sourceRoot":"","sources":["../src/coins.ts"],"names":[],"mappings":"AAkBA,MAAM,GAAG,GAAG,8EAA8E,CAAC;AAE3F,wDAAwD;AACxD,MAAM,CAAC,MAAM,KAAK,GAA8C;IAC9D,OAAO,EAAE;QACP,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,kBAAkB,EAAE;QACpF,MAAM,EAAE;YACN,MAAM,EAAE,QAAQ;YAChB,SAAS,EACP,oFAAoF;YACtF,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,+BAA+B;SAC7C;QACD,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM;YACd,SAAS,EACP,gFAAgF;YAClF,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,mCAAmC;SACjD;KACF;IACD,OAAO,EAAE;QACP,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,kBAAkB,EAAE;QACpF,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM;YACd,SAAS,EACP,gFAAgF;YAClF,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,8BAA8B;SAC5C;QACD,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM;YACd,SAAS,EACP,gFAAgF;YAClF,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,oCAAoC;SAClD;QACD,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM;YACd,SAAS,EACP,gFAAgF;YAClF,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,yBAAyB;SACvC;QACD,GAAG,EAAE;YACH,MAAM,EAAE,KAAK;YACb,SAAS,EACP,8EAA8E;YAChF,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,sBAAsB;SACpC;KACF;IACD,MAAM,EAAE;QACN,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,kBAAkB,EAAE;KACrF;CACF,CAAC;AAEF,+DAA+D;AAC/D,MAAM,UAAU,QAAQ,CAAC,OAAgB,EAAE,MAAc;IACvD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Network } from './sui-client.js';
|
|
2
|
+
/**
|
|
3
|
+
* DeepBook v3 on-chain constants, verified against @mysten/deepbook-v3
|
|
4
|
+
* (the official SDK) source. We hand-build the swap PTB on @mysten/sui v1
|
|
5
|
+
* rather than depend on that SDK, which now requires @mysten/sui v2.
|
|
6
|
+
*
|
|
7
|
+
* These are upgrade-stable but can change when DeepBook redeploys; every
|
|
8
|
+
* tool input can be overridden explicitly, so the registry is a
|
|
9
|
+
* convenience, not a hard dependency.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEEPBOOK_PACKAGE_ID: Record<Network, string>;
|
|
12
|
+
/** DEEP coin type (used to pay trading fees) per network. */
|
|
13
|
+
export declare const DEEP_TYPE: Record<Network, string>;
|
|
14
|
+
export interface PoolInfo {
|
|
15
|
+
pool_id: string;
|
|
16
|
+
base_type: string;
|
|
17
|
+
quote_type: string;
|
|
18
|
+
}
|
|
19
|
+
/** Flagship pools by key. Override pool_id/base_type/quote_type to use others. */
|
|
20
|
+
export declare const POOLS: Partial<Record<Network, Record<string, PoolInfo>>>;
|
package/dist/deepbook.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DeepBook v3 on-chain constants, verified against @mysten/deepbook-v3
|
|
3
|
+
* (the official SDK) source. We hand-build the swap PTB on @mysten/sui v1
|
|
4
|
+
* rather than depend on that SDK, which now requires @mysten/sui v2.
|
|
5
|
+
*
|
|
6
|
+
* These are upgrade-stable but can change when DeepBook redeploys; every
|
|
7
|
+
* tool input can be overridden explicitly, so the registry is a
|
|
8
|
+
* convenience, not a hard dependency.
|
|
9
|
+
*/
|
|
10
|
+
export const DEEPBOOK_PACKAGE_ID = {
|
|
11
|
+
testnet: '0x22be4cade64bf2d02412c7e8d0e8beea2f78828b948118d46735315409371a3c',
|
|
12
|
+
mainnet: '0x0e735f8c93a95722efd73521aca7a7652c0bb71ed1daf41b26dfd7d1ff71f748',
|
|
13
|
+
devnet: '',
|
|
14
|
+
};
|
|
15
|
+
/** DEEP coin type (used to pay trading fees) per network. */
|
|
16
|
+
export const DEEP_TYPE = {
|
|
17
|
+
testnet: '0x36dbef866a1d62bf7328989a10fb2f07d769f4ee587c0de4a0a256e57e0a58a8::deep::DEEP',
|
|
18
|
+
mainnet: '0xdeeb7a4662eec9f2f3def03fb937a663dddaa2e215b8078a284d026b7946c270::deep::DEEP',
|
|
19
|
+
devnet: '',
|
|
20
|
+
};
|
|
21
|
+
const SUI = '0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI';
|
|
22
|
+
const T_DBUSDC = '0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7::DBUSDC::DBUSDC';
|
|
23
|
+
const T_DEEP = DEEP_TYPE.testnet;
|
|
24
|
+
const M_USDC = '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC';
|
|
25
|
+
const M_DEEP = DEEP_TYPE.mainnet;
|
|
26
|
+
/** Flagship pools by key. Override pool_id/base_type/quote_type to use others. */
|
|
27
|
+
export const POOLS = {
|
|
28
|
+
testnet: {
|
|
29
|
+
SUI_DBUSDC: {
|
|
30
|
+
pool_id: '0x1c19362ca52b8ffd7a33cee805a67d40f31e6ba303753fd3a4cfdfacea7163a5',
|
|
31
|
+
base_type: SUI,
|
|
32
|
+
quote_type: T_DBUSDC,
|
|
33
|
+
},
|
|
34
|
+
DEEP_SUI: {
|
|
35
|
+
pool_id: '0x48c95963e9eac37a316b7ae04a0deb761bcdcc2b67912374d6036e7f0e9bae9f',
|
|
36
|
+
base_type: T_DEEP,
|
|
37
|
+
quote_type: SUI,
|
|
38
|
+
},
|
|
39
|
+
DEEP_DBUSDC: {
|
|
40
|
+
pool_id: '0xe86b991f8632217505fd859445f9803967ac84a9d4a1219065bf191fcb74b622',
|
|
41
|
+
base_type: T_DEEP,
|
|
42
|
+
quote_type: T_DBUSDC,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
mainnet: {
|
|
46
|
+
SUI_USDC: {
|
|
47
|
+
pool_id: '0xe05dafb5133bcffb8d59f4e12465dc0e9faeaa05e3e342a08fe135800e3e4407',
|
|
48
|
+
base_type: SUI,
|
|
49
|
+
quote_type: M_USDC,
|
|
50
|
+
},
|
|
51
|
+
DEEP_SUI: {
|
|
52
|
+
pool_id: '0xb663828d6217467c8a1838a03793da896cbe745b150ebd57d82f814ca579fc22',
|
|
53
|
+
base_type: M_DEEP,
|
|
54
|
+
quote_type: SUI,
|
|
55
|
+
},
|
|
56
|
+
DEEP_USDC: {
|
|
57
|
+
pool_id: '0xf948981b806057580f91622417534f491da5f61aeaf33d0ed8e69fd5691c95ce',
|
|
58
|
+
base_type: M_DEEP,
|
|
59
|
+
quote_type: M_USDC,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=deepbook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepbook.js","sourceRoot":"","sources":["../src/deepbook.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAA4B;IAC1D,OAAO,EAAE,oEAAoE;IAC7E,OAAO,EAAE,oEAAoE;IAC7E,MAAM,EAAE,EAAE;CACX,CAAC;AAEF,6DAA6D;AAC7D,MAAM,CAAC,MAAM,SAAS,GAA4B;IAChD,OAAO,EAAE,gFAAgF;IACzF,OAAO,EAAE,gFAAgF;IACzF,MAAM,EAAE,EAAE;CACX,CAAC;AAQF,MAAM,GAAG,GAAG,8EAA8E,CAAC;AAC3F,MAAM,QAAQ,GACZ,oFAAoF,CAAC;AACvF,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;AACjC,MAAM,MAAM,GAAG,gFAAgF,CAAC;AAChG,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;AAEjC,kFAAkF;AAClF,MAAM,CAAC,MAAM,KAAK,GAAuD;IACvE,OAAO,EAAE;QACP,UAAU,EAAE;YACV,OAAO,EAAE,oEAAoE;YAC7E,SAAS,EAAE,GAAG;YACd,UAAU,EAAE,QAAQ;SACrB;QACD,QAAQ,EAAE;YACR,OAAO,EAAE,oEAAoE;YAC7E,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,GAAG;SAChB;QACD,WAAW,EAAE;YACX,OAAO,EAAE,oEAAoE;YAC7E,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,QAAQ;SACrB;KACF;IACD,OAAO,EAAE;QACP,QAAQ,EAAE;YACR,OAAO,EAAE,oEAAoE;YAC7E,SAAS,EAAE,GAAG;YACd,UAAU,EAAE,MAAM;SACnB;QACD,QAAQ,EAAE;YACR,OAAO,EAAE,oEAAoE;YAC7E,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,GAAG;SAChB;QACD,SAAS,EAAE;YACT,OAAO,EAAE,oEAAoE;YAC7E,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,MAAM;SACnB;KACF;CACF,CAAC"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote (Streamable HTTP) entrypoint — Web Standards flavour.
|
|
3
|
+
*
|
|
4
|
+
* `handleMcpRequest(request)` is a runtime-agnostic Fetch handler: it runs
|
|
5
|
+
* on Vercel Edge, Cloudflare Workers, Deno, Bun, and Node 18+. Wire it to
|
|
6
|
+
* an HTTPS route and add that URL to Claude as a Custom Connector to use
|
|
7
|
+
* the Suisei MCP from the Claude web and mobile apps.
|
|
8
|
+
*
|
|
9
|
+
* Stateless: a fresh server + transport per request (no session store),
|
|
10
|
+
* which is what serverless wants. Reads work great over a remote
|
|
11
|
+
* connector; transaction-building tools return unsigned bytes — signing
|
|
12
|
+
* still happens host-side, so a remote host needs its own signing path.
|
|
13
|
+
*/
|
|
14
|
+
export interface McpHttpOptions {
|
|
15
|
+
/**
|
|
16
|
+
* If set, requests must carry `Authorization: Bearer <token>`. Falls
|
|
17
|
+
* back to the SUISEI_MCP_TOKEN env var (with SUI_SKILLS_MCP_TOKEN kept
|
|
18
|
+
* as a compatibility alias). Leave unset only for local testing — a
|
|
19
|
+
* public endpoint without a token is open to the world.
|
|
20
|
+
*/
|
|
21
|
+
authToken?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Handle one MCP request over Streamable HTTP. */
|
|
24
|
+
export declare function handleMcpRequest(request: Request, options?: McpHttpOptions): Promise<Response>;
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote (Streamable HTTP) entrypoint — Web Standards flavour.
|
|
3
|
+
*
|
|
4
|
+
* `handleMcpRequest(request)` is a runtime-agnostic Fetch handler: it runs
|
|
5
|
+
* on Vercel Edge, Cloudflare Workers, Deno, Bun, and Node 18+. Wire it to
|
|
6
|
+
* an HTTPS route and add that URL to Claude as a Custom Connector to use
|
|
7
|
+
* the Suisei MCP from the Claude web and mobile apps.
|
|
8
|
+
*
|
|
9
|
+
* Stateless: a fresh server + transport per request (no session store),
|
|
10
|
+
* which is what serverless wants. Reads work great over a remote
|
|
11
|
+
* connector; transaction-building tools return unsigned bytes — signing
|
|
12
|
+
* still happens host-side, so a remote host needs its own signing path.
|
|
13
|
+
*/
|
|
14
|
+
import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
|
|
15
|
+
import { createServer } from './server.js';
|
|
16
|
+
function envToken() {
|
|
17
|
+
const env = globalThis.process?.env;
|
|
18
|
+
return env?.SUISEI_MCP_TOKEN ?? env?.SUI_SKILLS_MCP_TOKEN;
|
|
19
|
+
}
|
|
20
|
+
function unauthorized() {
|
|
21
|
+
return new Response(JSON.stringify({
|
|
22
|
+
jsonrpc: '2.0',
|
|
23
|
+
error: { code: -32001, message: 'unauthorized' },
|
|
24
|
+
id: null,
|
|
25
|
+
}), { status: 401, headers: { 'content-type': 'application/json' } });
|
|
26
|
+
}
|
|
27
|
+
/** Handle one MCP request over Streamable HTTP. */
|
|
28
|
+
export async function handleMcpRequest(request, options = {}) {
|
|
29
|
+
const token = options.authToken ?? envToken();
|
|
30
|
+
if (token) {
|
|
31
|
+
const auth = request.headers.get('authorization') ?? '';
|
|
32
|
+
if (auth !== `Bearer ${token}`)
|
|
33
|
+
return unauthorized();
|
|
34
|
+
}
|
|
35
|
+
const server = createServer();
|
|
36
|
+
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
37
|
+
sessionIdGenerator: undefined, // stateless
|
|
38
|
+
});
|
|
39
|
+
await server.connect(transport);
|
|
40
|
+
return transport.handleRequest(request);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,wCAAwC,EAAE,MAAM,+DAA+D,CAAC;AACzH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAY3C,SAAS,QAAQ;IACf,MAAM,GAAG,GAAI,UAA6D,CAAC,OAAO,EAAE,GAAG,CAAC;IACxF,OAAO,GAAG,EAAE,gBAAgB,IAAI,GAAG,EAAE,oBAAoB,CAAC;AAC5D,CAAC;AAED,SAAS,YAAY;IACnB,OAAO,IAAI,QAAQ,CACjB,IAAI,CAAC,SAAS,CAAC;QACb,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE;QAChD,EAAE,EAAE,IAAI;KACT,CAAC,EACF,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,CACjE,CAAC;AACJ,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAgB,EAChB,UAA0B,EAAE;IAE5B,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,IAAI,QAAQ,EAAE,CAAC;IAC9C,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;QACxD,IAAI,IAAI,KAAK,UAAU,KAAK,EAAE;YAAE,OAAO,YAAY,EAAE,CAAC;IACxD,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,wCAAwC,CAAC;QAC7D,kBAAkB,EAAE,SAAS,EAAE,YAAY;KAC5C,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AAC1C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @suisei-mcp/mcp — stdio entrypoint.
|
|
4
|
+
*
|
|
5
|
+
* The product: the Suisei MCP server for the Sui stack. Plug into Claude
|
|
6
|
+
* Desktop, Cursor, or any MCP-aware agent and you get one-line tools to
|
|
7
|
+
* read chain state, call any Move function, transfer and stake SUI, mint
|
|
8
|
+
* badges, dry-run and submit transactions, and publish to Walrus.
|
|
9
|
+
*
|
|
10
|
+
* This entry uses stdio: the agent process spawns this binary and talks
|
|
11
|
+
* JSON-RPC over its stdin/stdout. For remote hosts (Claude Custom
|
|
12
|
+
* Connectors, web + mobile) use the HTTP entry in `http.ts` / `serve.ts`.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @suisei-mcp/mcp — stdio entrypoint.
|
|
4
|
+
*
|
|
5
|
+
* The product: the Suisei MCP server for the Sui stack. Plug into Claude
|
|
6
|
+
* Desktop, Cursor, or any MCP-aware agent and you get one-line tools to
|
|
7
|
+
* read chain state, call any Move function, transfer and stake SUI, mint
|
|
8
|
+
* badges, dry-run and submit transactions, and publish to Walrus.
|
|
9
|
+
*
|
|
10
|
+
* This entry uses stdio: the agent process spawns this binary and talks
|
|
11
|
+
* JSON-RPC over its stdin/stdout. For remote hosts (Claude Custom
|
|
12
|
+
* Connectors, web + mobile) use the HTTP entry in `http.ts` / `serve.ts`.
|
|
13
|
+
*/
|
|
14
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
15
|
+
import { createServer } from './server.js';
|
|
16
|
+
const server = createServer();
|
|
17
|
+
const transport = new StdioServerTransport();
|
|
18
|
+
await server.connect(transport);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node HTTP bridge for the Streamable HTTP transport.
|
|
3
|
+
*
|
|
4
|
+
* `handleMcpRequest` (http.ts) speaks the Web Fetch API. This adapter lets
|
|
5
|
+
* it serve Node `http`-style handlers — used by both the standalone server
|
|
6
|
+
* (serve.ts) and a Vercel Node serverless function. Node runtime is needed
|
|
7
|
+
* (not Edge) because some tools use the Node `Buffer` global.
|
|
8
|
+
*/
|
|
9
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
10
|
+
import { type McpHttpOptions } from './http.js';
|
|
11
|
+
/** Serve one MCP request from a Node http req/res pair. */
|
|
12
|
+
export declare function handleNodeRequest(req: IncomingMessage, res: ServerResponse, options?: McpHttpOptions): Promise<void>;
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node HTTP bridge for the Streamable HTTP transport.
|
|
3
|
+
*
|
|
4
|
+
* `handleMcpRequest` (http.ts) speaks the Web Fetch API. This adapter lets
|
|
5
|
+
* it serve Node `http`-style handlers — used by both the standalone server
|
|
6
|
+
* (serve.ts) and a Vercel Node serverless function. Node runtime is needed
|
|
7
|
+
* (not Edge) because some tools use the Node `Buffer` global.
|
|
8
|
+
*/
|
|
9
|
+
import { handleMcpRequest } from './http.js';
|
|
10
|
+
function readBody(req) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const chunks = [];
|
|
13
|
+
req.on('data', (c) => chunks.push(c));
|
|
14
|
+
req.on('end', () => resolve(Buffer.concat(chunks)));
|
|
15
|
+
req.on('error', reject);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
async function toFetchRequest(req) {
|
|
19
|
+
const host = req.headers.host ?? 'localhost';
|
|
20
|
+
const url = new URL(req.url ?? '/', `http://${host}`);
|
|
21
|
+
const headers = new Headers();
|
|
22
|
+
for (const [k, v] of Object.entries(req.headers)) {
|
|
23
|
+
if (Array.isArray(v))
|
|
24
|
+
v.forEach((vv) => headers.append(k, vv));
|
|
25
|
+
else if (v != null)
|
|
26
|
+
headers.set(k, v);
|
|
27
|
+
}
|
|
28
|
+
const method = req.method ?? 'GET';
|
|
29
|
+
const hasBody = method !== 'GET' && method !== 'HEAD';
|
|
30
|
+
const body = hasBody ? await readBody(req) : undefined;
|
|
31
|
+
return new Request(url, { method, headers, body: body && body.length ? body : undefined });
|
|
32
|
+
}
|
|
33
|
+
/** Serve one MCP request from a Node http req/res pair. */
|
|
34
|
+
export async function handleNodeRequest(req, res, options = {}) {
|
|
35
|
+
try {
|
|
36
|
+
const response = await handleMcpRequest(await toFetchRequest(req), options);
|
|
37
|
+
const buf = Buffer.from(await response.arrayBuffer());
|
|
38
|
+
const headers = {};
|
|
39
|
+
response.headers.forEach((value, key) => {
|
|
40
|
+
headers[key] = value;
|
|
41
|
+
});
|
|
42
|
+
res.writeHead(response.status, headers);
|
|
43
|
+
res.end(buf);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
res.writeHead(500, { 'content-type': 'application/json' });
|
|
47
|
+
res.end(JSON.stringify({
|
|
48
|
+
jsonrpc: '2.0',
|
|
49
|
+
error: { code: -32603, message: e instanceof Error ? e.message : String(e) },
|
|
50
|
+
id: null,
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,gBAAgB,EAAuB,MAAM,WAAW,CAAC;AAElE,SAAS,QAAQ,CAAC,GAAoB;IACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAW,CAAC,CAAC,CAAC;QAChD,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpD,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,GAAoB;IAChD,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;aAC1D,IAAI,CAAC,IAAI,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC;IACtD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACvD,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;AAC7F,CAAC;AAED,2DAA2D;AAC3D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAoB,EACpB,GAAmB,EACnB,UAA0B,EAAE;IAE5B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,MAAM,cAAc,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5E,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;QACtD,MAAM,OAAO,GAA2B,EAAE,CAAC;QAC3C,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACtC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACvB,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACxC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;YACb,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YAC5E,EAAE,EAAE,IAAI;SACT,CAAC,CACH,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/serve.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Standalone HTTP entrypoint — host the Suisei MCP anywhere.
|
|
4
|
+
*
|
|
5
|
+
* PORT=8787 SUISEI_MCP_TOKEN=secret npx suisei-mcp-serve
|
|
6
|
+
*
|
|
7
|
+
* Spins up a Node HTTP server and serves the Streamable HTTP transport via
|
|
8
|
+
* the shared node bridge. Point a Claude Custom Connector at
|
|
9
|
+
* https://<host>/ to use the toolkit from the Claude web and mobile apps.
|
|
10
|
+
* For serverless (Vercel Node / Cloudflare) call handleNodeRequest /
|
|
11
|
+
* handleMcpRequest from a route instead.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
package/dist/serve.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Standalone HTTP entrypoint — host the Suisei MCP anywhere.
|
|
4
|
+
*
|
|
5
|
+
* PORT=8787 SUISEI_MCP_TOKEN=secret npx suisei-mcp-serve
|
|
6
|
+
*
|
|
7
|
+
* Spins up a Node HTTP server and serves the Streamable HTTP transport via
|
|
8
|
+
* the shared node bridge. Point a Claude Custom Connector at
|
|
9
|
+
* https://<host>/ to use the toolkit from the Claude web and mobile apps.
|
|
10
|
+
* For serverless (Vercel Node / Cloudflare) call handleNodeRequest /
|
|
11
|
+
* handleMcpRequest from a route instead.
|
|
12
|
+
*/
|
|
13
|
+
import { createServer as createHttpServer } from 'node:http';
|
|
14
|
+
import { handleNodeRequest } from './node.js';
|
|
15
|
+
function envVar(name) {
|
|
16
|
+
return globalThis.process?.env?.[name];
|
|
17
|
+
}
|
|
18
|
+
const PORT = Number(envVar('PORT') ?? 8787);
|
|
19
|
+
const httpServer = createHttpServer((req, res) => {
|
|
20
|
+
void handleNodeRequest(req, res);
|
|
21
|
+
});
|
|
22
|
+
httpServer.listen(PORT, () => {
|
|
23
|
+
process.stderr.write(`suisei-mcp HTTP server on http://localhost:${PORT}\n`);
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,SAAS,MAAM,CAAC,IAAY;IAC1B,OAAQ,UAA6D,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AAC7F,CAAC;AAED,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;AAE5C,MAAM,UAAU,GAAG,gBAAgB,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IAC/C,KAAK,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACnC,CAAC,CAAC,CAAC;AAEH,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8CAA8C,IAAI,IAAI,CAAC,CAAC;AAC/E,CAAC,CAAC,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @suisei-mcp/mcp — server factory.
|
|
3
|
+
*
|
|
4
|
+
* Builds the Suisei MCP server with the full Sui-stack tool registry.
|
|
5
|
+
* Transport is chosen by the entrypoint: `index.ts` (stdio) for local
|
|
6
|
+
* hosts like Claude Desktop and Cursor; `http.ts` (Streamable HTTP) for
|
|
7
|
+
* remote hosts like Claude's Custom Connectors (web + mobile). Both call
|
|
8
|
+
* createServer() so there is exactly one tool registry.
|
|
9
|
+
*
|
|
10
|
+
* Write tools never hold keys — they return unsigned tx bytes for the
|
|
11
|
+
* host to sign, then sui_execute_signed_tx submits the signed result.
|
|
12
|
+
*
|
|
13
|
+
* The server identifies itself as "suisei" over the MCP protocol; tool
|
|
14
|
+
* names keep the sui_ prefix because they wrap the Sui chain, not the
|
|
15
|
+
* Suisei brand. Suisei is the agent toolkit; Sui is the chain it speaks.
|
|
16
|
+
*/
|
|
17
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
18
|
+
export declare const PKG_VERSION = "0.1.0";
|
|
19
|
+
/** Build a fresh MCP server with every Sui-stack tool registered. */
|
|
20
|
+
export declare function createServer(): Server;
|