@usenami/signer-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/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +212 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +197 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.d.ts +129 -0
- package/dist/lib.js +281 -0
- package/dist/lib.js.map +1 -0
- package/dist/parsers/asterdex.d.ts +35 -0
- package/dist/parsers/asterdex.js +79 -0
- package/dist/parsers/asterdex.js.map +1 -0
- package/dist/parsers/binance.d.ts +32 -0
- package/dist/parsers/binance.js +72 -0
- package/dist/parsers/binance.js.map +1 -0
- package/dist/parsers/index.d.ts +16 -0
- package/dist/parsers/index.js +25 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/okx.d.ts +34 -0
- package/dist/parsers/okx.js +104 -0
- package/dist/parsers/okx.js.map +1 -0
- package/dist/parsers/types.d.ts +62 -0
- package/dist/parsers/types.js +10 -0
- package/dist/parsers/types.js.map +1 -0
- package/package.json +65 -0
- package/server.json +62 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@usenami/signer-mcp` are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning is [SemVer](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- (placeholder for additions queued after the first publish)
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- (placeholder)
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- (placeholder)
|
|
15
|
+
|
|
16
|
+
## [0.1.0] — TBD (first publish, gated on signer gateway cutover)
|
|
17
|
+
|
|
18
|
+
Initial release. Five MCP tools backed by the Usenami Signer gateway, with keys that never leave an AWS Nitro Enclave.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- `list_venues` — read-only static manifest of supported venues (binance/okx/asterdex).
|
|
22
|
+
- `get_attestation` — Nitro PCR0 + AWS signature proving the running enclave matches the published build.
|
|
23
|
+
- `get_account` — equity / free margin / positions for a venue (Option-A: gateway returns signed read request, MCP submits + parses).
|
|
24
|
+
- `place_order` — single market or limit order on Binance USD-M Futures, OKX v5 perpetual swap, or Asterdex BSC perp. Signed inside the enclave; per-asset signature caps enforced server-side.
|
|
25
|
+
- `cancel_order` — cancel an outstanding order by venue + order_id (+ optional `symbol` for Binance/OKX cancel routes).
|
|
26
|
+
|
|
27
|
+
### Known limits (deliberate, see README §"What v0 deliberately does NOT do")
|
|
28
|
+
- stdio transport only — no SSE/HTTP.
|
|
29
|
+
- single account per venue per `SIGNER_API_TOKEN`.
|
|
30
|
+
- no withdrawals / transfers / leverage configuration / multi-venue routing / streaming.
|
|
31
|
+
- per-period rate caps (`$X / hour`) NOT enforced — documented gap; deferred to stateful-UPL work.
|
|
32
|
+
|
|
33
|
+
### Configuration
|
|
34
|
+
- `SIGNER_GATEWAY_URL` (default `https://signer.usenami.io`).
|
|
35
|
+
- `SIGNER_API_TOKEN` (required for everything except `list_venues`).
|
|
36
|
+
- `SIGNER_FETCH_TIMEOUT_MS` (default 30000ms).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Usenami
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# @usenami/signer-mcp
|
|
2
|
+
|
|
3
|
+
> Sign CEX orders from any MCP-aware AI agent — keys never leave an AWS Nitro Enclave.
|
|
4
|
+
|
|
5
|
+
`signer-mcp` is the public face of [Usenami Signer](https://usenami.io/signer). It gives Claude Desktop, Cursor, ElizaOS, and any other MCP-aware client a five-tool surface for trading real CEX/DEX accounts (Binance, OKX, Asterdex) without ever loading a private key into the agent's process — or yours.
|
|
6
|
+
|
|
7
|
+
Status: **v0 (alpha)**. List of venues, attestation, account read, and place/cancel order on testnet. See `_hub/DESIGN/signer-mcp-probe.md` in the parent repo for the full scope.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Why this exists
|
|
12
|
+
|
|
13
|
+
Every agent framework that touches a CEX today loads the API key into the agent process. That puts the secret on disk, in env vars, in npm packages, in prompt-engineered tool calls, and in your shell history. One prompt injection, one supply-chain compromise, one accidental log line, one curious co-worker — and the key leaks.
|
|
14
|
+
|
|
15
|
+
Signer takes the opposite approach. The signing key is generated **inside** an AWS Nitro Enclave attested by AWS itself. The enclave's measurement (`PCR0`) is published on `https://usenami.io/signer/attestations`. The MCP server you install here can ask the enclave to sign a specific order — bounded by an explicit policy (per-asset cap, per-period cap, allowed venues) — but it cannot read the key. Neither can the agent, your laptop, your IaC, or our own engineers.
|
|
16
|
+
|
|
17
|
+
If the agent gets compromised, the worst it can do is place orders inside your policy window. The key itself stays attested.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Quick start (Claude Desktop)
|
|
22
|
+
|
|
23
|
+
1. **Get a token.** Sign in at [usenami.io/signer](https://usenami.io/signer) and create an API token. The token is bound to a single policy — set per-venue caps before generating it.
|
|
24
|
+
2. **Edit `claude_desktop_config.json`.** Path is `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS.
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"signer": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["-y", "@usenami/signer-mcp"],
|
|
32
|
+
"env": {
|
|
33
|
+
"SIGNER_GATEWAY_URL": "https://signer.usenami.io",
|
|
34
|
+
"SIGNER_API_TOKEN": "sk_live_..."
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
3. **Restart Claude Desktop** and look for the 🔌 plug icon. You should see five tools listed under `signer`.
|
|
42
|
+
4. **Try the read-only tools first.** Ask Claude:
|
|
43
|
+
> "List the venues available through Signer, then return the current attestation document."
|
|
44
|
+
|
|
45
|
+
No funds at risk — these don't sign anything.
|
|
46
|
+
|
|
47
|
+
5. **Once you trust the attestation, place a tiny test order:**
|
|
48
|
+
> "Get my Binance account, then if I have at least $20 of free margin, place a market buy for 0.001 BTC."
|
|
49
|
+
|
|
50
|
+
If anything looks wrong, the agent can call `cancel_order` immediately.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Configuration
|
|
55
|
+
|
|
56
|
+
Environment variables passed via the `env` block of `claude_desktop_config.json` (or your client's equivalent):
|
|
57
|
+
|
|
58
|
+
| Variable | Required | Default | Notes |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| `SIGNER_GATEWAY_URL` | no | `https://signer.usenami.io` | Override for self-hosted or staging deployments. |
|
|
61
|
+
| `SIGNER_API_TOKEN` | yes (for paid tools) | — | Bearer token issued by usenami.io/signer. `list_venues` works without one; everything else requires it. |
|
|
62
|
+
| `SIGNER_FETCH_TIMEOUT_MS` | no | `30000` | Per-request fetch timeout in ms. Lower for CI / smoke tests; raise on slow links. Must be positive integer. |
|
|
63
|
+
|
|
64
|
+
The MCP server itself stores nothing on disk. Tokens are read from environment on startup and held in memory for the lifetime of the process — kill the agent, the token goes with it.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Tool reference
|
|
69
|
+
|
|
70
|
+
### `list_venues`
|
|
71
|
+
|
|
72
|
+
Returns the static manifest of venues this Signer can sign for. **Read-only**, does not contact the gateway, works without a token. Call this first to discover what's supported.
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"venues": [
|
|
77
|
+
{
|
|
78
|
+
"venue": "binance",
|
|
79
|
+
"asset_class": "perp",
|
|
80
|
+
"auth_scheme": "hmac_sha256",
|
|
81
|
+
"notes": "..."
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
"count": 1
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### `get_attestation`
|
|
89
|
+
|
|
90
|
+
Returns the Nitro attestation document for the currently-running enclave. The PCR0 measurement here is what AWS signed when it booted the enclave; you can verify it matches the published build by hashing the corresponding EIF and comparing.
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"pcr0": "...sha384 hex...",
|
|
95
|
+
"pcr1": "...",
|
|
96
|
+
"pcr2": "...",
|
|
97
|
+
"signature": "...AWS-issued...",
|
|
98
|
+
"issued_at": "2026-05-31T18:00:00Z"
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Read-only.
|
|
103
|
+
|
|
104
|
+
### `get_account`
|
|
105
|
+
|
|
106
|
+
Returns equity, free margin, and open positions for a venue.
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"venue": "binance",
|
|
111
|
+
"equity_usd": 145.32,
|
|
112
|
+
"free_margin_usd": 92.10,
|
|
113
|
+
"positions": [
|
|
114
|
+
{ "symbol": "BTCUSDT", "qty": 0.002, "entry_price": 67120.5 }
|
|
115
|
+
],
|
|
116
|
+
"updated_at": "2026-05-31T18:01:11Z"
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Read-only. Requires `SIGNER_API_TOKEN`.
|
|
121
|
+
|
|
122
|
+
### `place_order`
|
|
123
|
+
|
|
124
|
+
Place a single market or limit order. The enclave signs the payload after checking policy caps.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
- `venue` — one of `binance | okx | asterdex`
|
|
128
|
+
- `symbol` — venue-native symbol (`BTCUSDT`, `BTC-USDT-SWAP`, etc.)
|
|
129
|
+
- `side` — `buy` | `sell`
|
|
130
|
+
- `qty` — base-asset quantity (e.g. 0.001 for 0.001 BTC). Not USD-notional.
|
|
131
|
+
- `type` — `market` | `limit`
|
|
132
|
+
- `price` — required if `type=limit`, ignored if `type=market`
|
|
133
|
+
- `policy_id` — optional override; defaults to the policy bound to your token
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"venue": "binance",
|
|
138
|
+
"order_id": "...",
|
|
139
|
+
"status": "FILLED",
|
|
140
|
+
"filled_qty": 0.001,
|
|
141
|
+
"avg_fill_price": 67128.9,
|
|
142
|
+
"policy_id": "default",
|
|
143
|
+
"attested_at": "..."
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Destructive.** Requires `SIGNER_API_TOKEN`. v0 routes Binance/OKX to testnet until pilot graduates.
|
|
148
|
+
|
|
149
|
+
### `cancel_order`
|
|
150
|
+
|
|
151
|
+
Cancels an outstanding order by its venue order id. Idempotent — cancelling an already-filled or non-existent order returns `ok: false` with a venue reason instead of erroring.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
- `venue` — same enum as `place_order`
|
|
155
|
+
- `order_id` — the venue id returned by `place_order`
|
|
156
|
+
|
|
157
|
+
Requires `SIGNER_API_TOKEN`.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Verifying the attestation
|
|
162
|
+
|
|
163
|
+
A trustworthy Signer is one whose enclave measurement matches a build you can audit. The workflow:
|
|
164
|
+
|
|
165
|
+
1. Call `get_attestation` and copy the returned `pcr0`.
|
|
166
|
+
2. Visit [usenami.io/signer/attestations](https://usenami.io/signer/attestations).
|
|
167
|
+
3. Cross-reference the PCR0 against the published build for the current production version.
|
|
168
|
+
4. Optionally rebuild the EIF from source (instructions on the same page) and verify the SHA384 hash yourself.
|
|
169
|
+
|
|
170
|
+
If the published PCR0 doesn't match what `get_attestation` returns, **don't trade**. Open an issue.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## What v0 deliberately does NOT do
|
|
175
|
+
|
|
176
|
+
Per scope guard `_hub/DESIGN/signer-mcp-probe.md` §6:
|
|
177
|
+
|
|
178
|
+
- No multi-tenant: one account per venue per token.
|
|
179
|
+
- No UPL editing UI: policies are set out-of-band on usenami.io/signer.
|
|
180
|
+
- No WebSocket / streaming tools — REST only.
|
|
181
|
+
- No cross-venue routing (`place_order` takes one venue).
|
|
182
|
+
- No leverage configuration (`set_leverage`) — uses account defaults.
|
|
183
|
+
- No withdrawals / transfers (closest is `cancel_order`).
|
|
184
|
+
- No TWAP / iceberg — single-shot orders only.
|
|
185
|
+
- stdio transport only — no SSE or remote HTTP.
|
|
186
|
+
|
|
187
|
+
If you need any of the above, file an issue describing the use case. v0 keeps the surface tight on purpose.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Development
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# install deps
|
|
195
|
+
npm install
|
|
196
|
+
|
|
197
|
+
# typecheck + build
|
|
198
|
+
npm run build
|
|
199
|
+
|
|
200
|
+
# run from source against staging
|
|
201
|
+
SIGNER_GATEWAY_URL=https://staging.signer.usenami.io \
|
|
202
|
+
SIGNER_API_TOKEN=sk_test_... \
|
|
203
|
+
npm run dev
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The transport is stdio; you'll need an MCP-aware client to actually exercise the tools. The Anthropic [`mcp-inspector`](https://github.com/modelcontextprotocol/inspector) is the fastest way to poke at it locally.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT. See [LICENSE](LICENSE).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @usenami/signer-mcp — v0 (MCP entry point)
|
|
4
|
+
*
|
|
5
|
+
* Sign CEX orders from any MCP-aware AI agent (Claude Desktop, Cursor, ElizaOS)
|
|
6
|
+
* with keys that never leave an AWS Nitro Enclave.
|
|
7
|
+
*
|
|
8
|
+
* Per the scoping doc `_hub/DESIGN/signer-mcp-probe.md` (§2), v0 ships five
|
|
9
|
+
* tools backed by the Usenami Signer gateway. Tool logic lives in `lib.ts`
|
|
10
|
+
* so unit tests can exercise it without booting the MCP transport.
|
|
11
|
+
*
|
|
12
|
+
* Configuration (claude_desktop_config.json):
|
|
13
|
+
*
|
|
14
|
+
* {
|
|
15
|
+
* "mcpServers": {
|
|
16
|
+
* "signer": {
|
|
17
|
+
* "command": "npx",
|
|
18
|
+
* "args": ["-y", "@usenami/signer-mcp"],
|
|
19
|
+
* "env": {
|
|
20
|
+
* "SIGNER_GATEWAY_URL": "https://signer.usenami.io",
|
|
21
|
+
* "SIGNER_API_TOKEN": "...issued from signer.usenami.io..."
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* Scope-guard §6 of the design doc: stdio only, no multi-tenant, no UPL UI,
|
|
28
|
+
* no streaming, no cross-venue routing, no withdrawals — the enclave key
|
|
29
|
+
* NEVER leaves the enclave; this process only proxies intents.
|
|
30
|
+
*/
|
|
31
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @usenami/signer-mcp — v0 (MCP entry point)
|
|
4
|
+
*
|
|
5
|
+
* Sign CEX orders from any MCP-aware AI agent (Claude Desktop, Cursor, ElizaOS)
|
|
6
|
+
* with keys that never leave an AWS Nitro Enclave.
|
|
7
|
+
*
|
|
8
|
+
* Per the scoping doc `_hub/DESIGN/signer-mcp-probe.md` (§2), v0 ships five
|
|
9
|
+
* tools backed by the Usenami Signer gateway. Tool logic lives in `lib.ts`
|
|
10
|
+
* so unit tests can exercise it without booting the MCP transport.
|
|
11
|
+
*
|
|
12
|
+
* Configuration (claude_desktop_config.json):
|
|
13
|
+
*
|
|
14
|
+
* {
|
|
15
|
+
* "mcpServers": {
|
|
16
|
+
* "signer": {
|
|
17
|
+
* "command": "npx",
|
|
18
|
+
* "args": ["-y", "@usenami/signer-mcp"],
|
|
19
|
+
* "env": {
|
|
20
|
+
* "SIGNER_GATEWAY_URL": "https://signer.usenami.io",
|
|
21
|
+
* "SIGNER_API_TOKEN": "...issued from signer.usenami.io..."
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* Scope-guard §6 of the design doc: stdio only, no multi-tenant, no UPL UI,
|
|
28
|
+
* no streaming, no cross-venue routing, no withdrawals — the enclave key
|
|
29
|
+
* NEVER leaves the enclave; this process only proxies intents.
|
|
30
|
+
*/
|
|
31
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
32
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
33
|
+
import { z } from "zod";
|
|
34
|
+
import { PACKAGE_VERSION, STATIC_VENUES, handleCancelOrder, handleGetAccount, handleGetAttestation, handleListVenues, handlePlaceOrder, } from "./lib.js";
|
|
35
|
+
import { getAccountParser } from "./parsers/index.js";
|
|
36
|
+
// ── Environment ──
|
|
37
|
+
const GATEWAY_URL = (process.env.SIGNER_GATEWAY_URL || "https://signer.usenami.io").replace(/\/+$/, "");
|
|
38
|
+
const API_TOKEN = (process.env.SIGNER_API_TOKEN || "").trim();
|
|
39
|
+
// Optional override for fetch timeout — useful when running the smoke test
|
|
40
|
+
// against an unreachable host or in CI where 30s is too slow. Validated to
|
|
41
|
+
// be a positive integer; falls back to lib's DEFAULT_FETCH_TIMEOUT_MS otherwise.
|
|
42
|
+
const TIMEOUT_RAW = (process.env.SIGNER_FETCH_TIMEOUT_MS || "").trim();
|
|
43
|
+
const TIMEOUT_MS = (() => {
|
|
44
|
+
if (TIMEOUT_RAW.length === 0)
|
|
45
|
+
return undefined;
|
|
46
|
+
const n = parseInt(TIMEOUT_RAW, 10);
|
|
47
|
+
return Number.isFinite(n) && n > 0 ? n : undefined;
|
|
48
|
+
})();
|
|
49
|
+
const cfg = {
|
|
50
|
+
gatewayUrl: GATEWAY_URL,
|
|
51
|
+
apiToken: API_TOKEN || undefined,
|
|
52
|
+
fetchTimeoutMs: TIMEOUT_MS,
|
|
53
|
+
};
|
|
54
|
+
const HAS_TOKEN = API_TOKEN.length > 0;
|
|
55
|
+
// ── MCP tool annotations ──
|
|
56
|
+
const READ_ONLY_ANNOTATIONS = {
|
|
57
|
+
readOnlyHint: true,
|
|
58
|
+
destructiveHint: false,
|
|
59
|
+
idempotentHint: true,
|
|
60
|
+
openWorldHint: true,
|
|
61
|
+
};
|
|
62
|
+
const WRITE_DESTRUCTIVE_ANNOTATIONS = {
|
|
63
|
+
readOnlyHint: false,
|
|
64
|
+
destructiveHint: true,
|
|
65
|
+
idempotentHint: false,
|
|
66
|
+
openWorldHint: true,
|
|
67
|
+
};
|
|
68
|
+
// ── Tool descriptions (read by agents) ──
|
|
69
|
+
const DESC_LIST_VENUES = "List the venues this Signer can sign trades for. Returns the venue id, " +
|
|
70
|
+
"asset class (perp / spot / margin), and auth scheme (hmac / eip712 / " +
|
|
71
|
+
"ed25519). Read-only static manifest — does NOT need the Signer gateway " +
|
|
72
|
+
"to be reachable. Call this first to discover what's signable.";
|
|
73
|
+
const DESC_GET_ATTESTATION = "Return the Signer enclave's AWS Nitro attestation document (PCR0, " +
|
|
74
|
+
"PCR1, PCR2 measurements + AWS-issued signature). This proves the code " +
|
|
75
|
+
"currently signing your orders matches the published source. The enclave's " +
|
|
76
|
+
"signing key NEVER leaves attested code. Verify the PCR0 against " +
|
|
77
|
+
"https://usenami.io/signer/attestations before trusting any place_order.";
|
|
78
|
+
const DESC_GET_ACCOUNT = "Return equity, free margin, and open positions for a venue. Read-only " +
|
|
79
|
+
"(does not sign anything that mutates state). Use BEFORE place_order to " +
|
|
80
|
+
"confirm the account has margin. Requires SIGNER_API_TOKEN.";
|
|
81
|
+
const DESC_PLACE_ORDER = "Place a single order on the named venue. The Signer enclave will sign " +
|
|
82
|
+
"the venue-native payload using a key that has never been exported. " +
|
|
83
|
+
"Policy enforced server-side: orders that exceed per-asset caps are " +
|
|
84
|
+
"rejected by the enclave before signing. Returns the venue's order_id on " +
|
|
85
|
+
"success. Side effect: real or testnet trade depending on venue env.";
|
|
86
|
+
const DESC_CANCEL_ORDER = "Cancel an outstanding order by its venue order_id. Signed inside the " +
|
|
87
|
+
"enclave just like place_order. Returns the cancellation receipt from " +
|
|
88
|
+
"the venue. Idempotent: cancelling a non-existent / already-filled " +
|
|
89
|
+
"order returns ok=false with a reason from the venue.";
|
|
90
|
+
// ── Schemas ──
|
|
91
|
+
const VenueIdSchema = z
|
|
92
|
+
.enum(STATIC_VENUES.map((v) => v.venue))
|
|
93
|
+
.describe("Venue identifier. Must match an entry returned by list_venues — " +
|
|
94
|
+
"any other value will be rejected by the gateway.");
|
|
95
|
+
const TickerSchema = z
|
|
96
|
+
.string()
|
|
97
|
+
.min(1)
|
|
98
|
+
.max(32)
|
|
99
|
+
.regex(/^[A-Z0-9_-]+$/, "Use venue-native symbol format (no slash)")
|
|
100
|
+
.describe("Venue-native trading symbol. Examples: BTCUSDT (binance), " +
|
|
101
|
+
"BTC-USDT-SWAP (okx), BTC-USD (asterdex). Case-sensitive.");
|
|
102
|
+
const OrderSideSchema = z
|
|
103
|
+
.enum(["buy", "sell"])
|
|
104
|
+
.describe("buy = long open / short close; sell = short open / long close.");
|
|
105
|
+
const OrderTypeSchema = z
|
|
106
|
+
.enum(["market", "limit"])
|
|
107
|
+
.describe("market = immediate fill at venue best; limit = resting order at `price`.");
|
|
108
|
+
const QuantitySchema = z
|
|
109
|
+
.number()
|
|
110
|
+
.positive()
|
|
111
|
+
.describe("Order quantity in base asset (e.g. BTC), NOT in USD-notional. Some " +
|
|
112
|
+
"venues require a minimum (Binance: 0.001 BTC). Refer to venue docs.");
|
|
113
|
+
const PriceSchema = z
|
|
114
|
+
.number()
|
|
115
|
+
.positive()
|
|
116
|
+
.optional()
|
|
117
|
+
.describe("Limit price in quote asset. Required for type=limit, ignored for " +
|
|
118
|
+
"type=market.");
|
|
119
|
+
const PolicyIdSchema = z
|
|
120
|
+
.string()
|
|
121
|
+
.optional()
|
|
122
|
+
.describe("Optional policy id override. If omitted, the gateway uses the default " +
|
|
123
|
+
"policy bound to the provided SIGNER_API_TOKEN.");
|
|
124
|
+
// ── Server setup ──
|
|
125
|
+
const server = new McpServer({
|
|
126
|
+
name: "@usenami/signer-mcp",
|
|
127
|
+
version: PACKAGE_VERSION,
|
|
128
|
+
});
|
|
129
|
+
server.registerTool("list_venues", {
|
|
130
|
+
description: DESC_LIST_VENUES,
|
|
131
|
+
inputSchema: {},
|
|
132
|
+
annotations: { ...READ_ONLY_ANNOTATIONS, title: "List supported venues" },
|
|
133
|
+
}, async () => handleListVenues());
|
|
134
|
+
server.registerTool("get_attestation", {
|
|
135
|
+
description: DESC_GET_ATTESTATION,
|
|
136
|
+
inputSchema: {},
|
|
137
|
+
annotations: {
|
|
138
|
+
...READ_ONLY_ANNOTATIONS,
|
|
139
|
+
title: "Get Nitro attestation document",
|
|
140
|
+
},
|
|
141
|
+
}, async () => handleGetAttestation(cfg));
|
|
142
|
+
server.registerTool("get_account", {
|
|
143
|
+
description: DESC_GET_ACCOUNT,
|
|
144
|
+
inputSchema: { venue: VenueIdSchema },
|
|
145
|
+
annotations: {
|
|
146
|
+
...READ_ONLY_ANNOTATIONS,
|
|
147
|
+
title: "Get venue account snapshot",
|
|
148
|
+
},
|
|
149
|
+
}, async (args) => handleGetAccount(cfg, args, getAccountParser));
|
|
150
|
+
server.registerTool("place_order", {
|
|
151
|
+
description: DESC_PLACE_ORDER,
|
|
152
|
+
inputSchema: {
|
|
153
|
+
venue: VenueIdSchema,
|
|
154
|
+
symbol: TickerSchema,
|
|
155
|
+
side: OrderSideSchema,
|
|
156
|
+
qty: QuantitySchema,
|
|
157
|
+
type: OrderTypeSchema,
|
|
158
|
+
price: PriceSchema,
|
|
159
|
+
policy_id: PolicyIdSchema,
|
|
160
|
+
},
|
|
161
|
+
annotations: {
|
|
162
|
+
...WRITE_DESTRUCTIVE_ANNOTATIONS,
|
|
163
|
+
title: "Place a single order via Signer enclave",
|
|
164
|
+
},
|
|
165
|
+
}, async (args) => handlePlaceOrder(cfg, args));
|
|
166
|
+
server.registerTool("cancel_order", {
|
|
167
|
+
description: DESC_CANCEL_ORDER,
|
|
168
|
+
inputSchema: {
|
|
169
|
+
venue: VenueIdSchema,
|
|
170
|
+
order_id: z
|
|
171
|
+
.string()
|
|
172
|
+
.min(1)
|
|
173
|
+
.describe("Venue-native order identifier returned by place_order."),
|
|
174
|
+
symbol: TickerSchema.optional().describe("Venue-native symbol — REQUIRED for binance + okx cancels (their " +
|
|
175
|
+
"REST APIs need the symbol on the cancel route). Optional for " +
|
|
176
|
+
"venues that derive it from order_id alone."),
|
|
177
|
+
},
|
|
178
|
+
annotations: {
|
|
179
|
+
readOnlyHint: false,
|
|
180
|
+
destructiveHint: false,
|
|
181
|
+
idempotentHint: true,
|
|
182
|
+
openWorldHint: true,
|
|
183
|
+
title: "Cancel an outstanding order",
|
|
184
|
+
},
|
|
185
|
+
}, async (args) => handleCancelOrder(cfg, args));
|
|
186
|
+
// ── Boot ──
|
|
187
|
+
async function main() {
|
|
188
|
+
const transport = new StdioServerTransport();
|
|
189
|
+
await server.connect(transport);
|
|
190
|
+
process.stderr.write(`[signer-mcp v${PACKAGE_VERSION}] connected — gateway=${GATEWAY_URL} ` +
|
|
191
|
+
`auth=${HAS_TOKEN ? "yes" : "no"}\n`);
|
|
192
|
+
}
|
|
193
|
+
main().catch((err) => {
|
|
194
|
+
process.stderr.write(`[signer-mcp] fatal: ${err.stack ?? err}\n`);
|
|
195
|
+
process.exit(1);
|
|
196
|
+
});
|
|
197
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/lib.d.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core handlers and helpers for @usenami/signer-mcp.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from index.ts so unit tests can exercise the gateway-call paths
|
|
5
|
+
* without booting a real MCP transport. index.ts wires these into MCP tools.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PACKAGE_VERSION = "0.1.0";
|
|
8
|
+
export declare const DEFAULT_FETCH_TIMEOUT_MS = 30000;
|
|
9
|
+
export interface VenueEntry {
|
|
10
|
+
venue: string;
|
|
11
|
+
asset_class: string;
|
|
12
|
+
auth_scheme: "hmac_sha256" | "eip712" | "ed25519";
|
|
13
|
+
network?: string;
|
|
14
|
+
notes?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare const STATIC_VENUES: VenueEntry[];
|
|
17
|
+
export declare class GatewayError extends Error {
|
|
18
|
+
readonly status: number;
|
|
19
|
+
readonly body: string;
|
|
20
|
+
readonly endpoint: string;
|
|
21
|
+
constructor(status: number, body: string, endpoint: string);
|
|
22
|
+
}
|
|
23
|
+
export interface GatewayConfig {
|
|
24
|
+
gatewayUrl: string;
|
|
25
|
+
apiToken?: string;
|
|
26
|
+
fetchTimeoutMs?: number;
|
|
27
|
+
/** Injected for tests; defaults to global fetch. */
|
|
28
|
+
fetchImpl?: typeof fetch;
|
|
29
|
+
}
|
|
30
|
+
export interface GatewayCallOpts {
|
|
31
|
+
method?: "GET" | "POST" | "DELETE";
|
|
32
|
+
body?: unknown;
|
|
33
|
+
authRequired?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Single chokepoint for all gateway HTTP. Tests inject a `fetchImpl` and
|
|
37
|
+
* assert against the dispatched request.
|
|
38
|
+
*
|
|
39
|
+
* Edge cases handled:
|
|
40
|
+
* - Missing token when authRequired → thrown with actionable message.
|
|
41
|
+
* - Empty 200 OK body → returned as undefined (rare but possible on some
|
|
42
|
+
* venues' cancel-already-filled paths).
|
|
43
|
+
* - Non-2xx → GatewayError carries status + body for the agent to inspect.
|
|
44
|
+
* - Timeout → AbortController + clearTimeout via try/finally.
|
|
45
|
+
*/
|
|
46
|
+
export declare function callGateway<T>(path: string, opts: GatewayCallOpts, cfg: GatewayConfig): Promise<T>;
|
|
47
|
+
export interface ToolResult {
|
|
48
|
+
content: Array<{
|
|
49
|
+
type: "text";
|
|
50
|
+
text: string;
|
|
51
|
+
}>;
|
|
52
|
+
isError?: true;
|
|
53
|
+
[x: string]: unknown;
|
|
54
|
+
}
|
|
55
|
+
export declare function toolJson<T>(value: T): ToolResult;
|
|
56
|
+
export declare function toolError(message: string, hint?: string): ToolResult;
|
|
57
|
+
export interface PlaceOrderInput {
|
|
58
|
+
venue: string;
|
|
59
|
+
symbol: string;
|
|
60
|
+
side: "buy" | "sell";
|
|
61
|
+
qty: number;
|
|
62
|
+
type: "market" | "limit";
|
|
63
|
+
price?: number;
|
|
64
|
+
policy_id?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface CancelOrderInput {
|
|
67
|
+
venue: string;
|
|
68
|
+
order_id: string;
|
|
69
|
+
/**
|
|
70
|
+
* Required for binance + okx (their REST APIs need symbol on the cancel
|
|
71
|
+
* route). Optional for venues that derive it from order_id alone.
|
|
72
|
+
*/
|
|
73
|
+
symbol?: string;
|
|
74
|
+
}
|
|
75
|
+
export interface SignedRequest {
|
|
76
|
+
venue: string;
|
|
77
|
+
method: "GET" | "POST" | "DELETE";
|
|
78
|
+
url: string;
|
|
79
|
+
headers: Record<string, string>;
|
|
80
|
+
body?: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Submit a single signed request to a venue and return parsed JSON (or text
|
|
84
|
+
* if the response isn't JSON). Errors include the venue endpoint + status so
|
|
85
|
+
* the agent can reason about which side failed.
|
|
86
|
+
*/
|
|
87
|
+
export declare function submitSignedRequest(req: SignedRequest, fetchImpl?: typeof fetch, timeoutMs?: number): Promise<unknown>;
|
|
88
|
+
/**
|
|
89
|
+
* Submit a "bundle" — either a single SignedRequest or a map of named
|
|
90
|
+
* SignedRequests (`{balance: ..., positions: ...}`). Parallel for composite,
|
|
91
|
+
* returns the same shape with raw venue responses in place of each request.
|
|
92
|
+
*/
|
|
93
|
+
export declare function submitSignedBundle(bundle: unknown, fetchImpl?: typeof fetch, timeoutMs?: number): Promise<unknown>;
|
|
94
|
+
export declare function handleListVenues(): Promise<ToolResult>;
|
|
95
|
+
export declare function handleGetAttestation(cfg: GatewayConfig): Promise<ToolResult>;
|
|
96
|
+
/**
|
|
97
|
+
* Option-A flow for /account:
|
|
98
|
+
* 1. POST gateway /account/<venue> → returns SignedRequest bundle
|
|
99
|
+
* 2. submitSignedBundle → fetch venue with signed headers
|
|
100
|
+
* 3. dispatch raw response to venue-specific parser
|
|
101
|
+
* 4. return NormalizedAccount
|
|
102
|
+
*
|
|
103
|
+
* If the gateway response is NOT a SignedRequest (e.g. asterdex indexer
|
|
104
|
+
* returns parsed data directly), we feed the raw payload to the parser
|
|
105
|
+
* unchanged — parser is tolerant of both shapes.
|
|
106
|
+
*/
|
|
107
|
+
export declare function handleGetAccount(cfg: GatewayConfig, args: {
|
|
108
|
+
venue: string;
|
|
109
|
+
}, getParser: (venue: string) => AccountParser | undefined): Promise<ToolResult>;
|
|
110
|
+
/**
|
|
111
|
+
* Option-A flow for /sign/order:
|
|
112
|
+
* 1. POST gateway /sign/order with intent body → returns SignedRequest
|
|
113
|
+
* 2. submitSignedRequest → fetch venue, return raw venue receipt
|
|
114
|
+
* 3. agent sees venue's native response (order_id format etc)
|
|
115
|
+
*
|
|
116
|
+
* No parser layer here — order receipts are per-venue and we don't normalize
|
|
117
|
+
* them in v0. Agent inspects raw response to decide next action.
|
|
118
|
+
*/
|
|
119
|
+
export declare function handlePlaceOrder(cfg: GatewayConfig, args: PlaceOrderInput): Promise<ToolResult>;
|
|
120
|
+
/**
|
|
121
|
+
* Option-A flow for /sign/cancel — same as place_order.
|
|
122
|
+
*
|
|
123
|
+
* Note: Binance + OKX cancel routes require `symbol` on top of `order_id`.
|
|
124
|
+
* The MCP tool exposes optional `symbol` to support these (and ignores it
|
|
125
|
+
* for venues that don't need it).
|
|
126
|
+
*/
|
|
127
|
+
export declare function handleCancelOrder(cfg: GatewayConfig, args: CancelOrderInput): Promise<ToolResult>;
|
|
128
|
+
import type { AccountParser } from "./parsers/types.js";
|
|
129
|
+
export type { AccountParser };
|