@stratabook/mcp 0.1.5 → 0.1.6
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 +55 -148
- package/dist/src/generated-harness.d.ts +78 -3
- package/dist/src/generated-harness.js +99 -3
- package/dist/src/server.d.ts +2 -1
- package/dist/src/server.js +129 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,178 +1,85 @@
|
|
|
1
|
-
|
|
2
|
-
<img src="./assets/readme-hero.svg" alt="Strata — The deepest book in DeFi." width="100%" />
|
|
3
|
-
</p>
|
|
1
|
+
# Strata MCP
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
Official capability-gated MCP access to Strata and Sonar. The server is a thin adapter
|
|
4
|
+
over `@stratabook/sdk`: it follows the live capability catalog and contains no
|
|
5
|
+
private execution logic.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
Put live Strata markets and Sonar pricing inside any MCP-compatible agent.
|
|
9
|
-
</p>
|
|
7
|
+
## Local stdio
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<a href="https://github.com/alsk1992/strata-sdk-ts">TypeScript</a>
|
|
15
|
-
·
|
|
16
|
-
<a href="https://github.com/alsk1992/strata-agent-skills">Agent Skills</a>
|
|
17
|
-
·
|
|
18
|
-
<a href="https://stratabook.app">Strata</a>
|
|
19
|
-
</p>
|
|
20
|
-
|
|
21
|
-
One hosted connection gives an agent current market availability and
|
|
22
|
-
decision-ready quotes from Sonar—Strata's unified liquidity and matching
|
|
23
|
-
system. No local daemon is required.
|
|
24
|
-
|
|
25
|
-
## Connect
|
|
9
|
+
```sh
|
|
10
|
+
npx -y @stratabook/mcp
|
|
11
|
+
```
|
|
26
12
|
|
|
27
|
-
|
|
13
|
+
Example client configuration:
|
|
28
14
|
|
|
29
15
|
```json
|
|
30
16
|
{
|
|
31
17
|
"mcpServers": {
|
|
32
18
|
"strata": {
|
|
33
|
-
"
|
|
34
|
-
"
|
|
19
|
+
"command": "npx",
|
|
20
|
+
"args": ["-y", "@stratabook/mcp"]
|
|
35
21
|
}
|
|
36
22
|
}
|
|
37
23
|
}
|
|
38
24
|
```
|
|
39
25
|
|
|
40
|
-
|
|
41
|
-
Strata tools currently available to it.
|
|
42
|
-
|
|
43
|
-
## See Strata answer from a terminal
|
|
44
|
-
|
|
45
|
-
Use the official MCP Inspector (Node.js 22.7.5+) to list the hosted tools:
|
|
46
|
-
|
|
47
|
-
```sh
|
|
48
|
-
npx -y @modelcontextprotocol/inspector --cli \
|
|
49
|
-
https://api.stratabook.app/mcp \
|
|
50
|
-
--transport http \
|
|
51
|
-
--method tools/list
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Call Strata directly:
|
|
55
|
-
|
|
56
|
-
```sh
|
|
57
|
-
npx -y @modelcontextprotocol/inspector --cli \
|
|
58
|
-
https://api.stratabook.app/mcp \
|
|
59
|
-
--transport http \
|
|
60
|
-
--method tools/call \
|
|
61
|
-
--tool-name strata_markets \
|
|
62
|
-
--tool-arg includePaused=false
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Request a live Sonar quote through the same connection:
|
|
66
|
-
|
|
67
|
-
```sh
|
|
68
|
-
npx -y @modelcontextprotocol/inspector --cli \
|
|
69
|
-
https://api.stratabook.app/mcp \
|
|
70
|
-
--transport http \
|
|
71
|
-
--method tools/call \
|
|
72
|
-
--tool-name strata_quote \
|
|
73
|
-
--tool-arg market=SOL/USDC \
|
|
74
|
-
--tool-arg side=sell \
|
|
75
|
-
--tool-arg 'amountInAtoms="10000000"'
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
The response is structured data, ready for terminals, scripts, and agents.
|
|
79
|
-
|
|
80
|
-
## What lands in the agent
|
|
81
|
-
|
|
82
|
-
| Tool | Result |
|
|
83
|
-
| --- | --- |
|
|
84
|
-
| `strata_capabilities` | The Strata features available in the current session |
|
|
85
|
-
| `strata_markets` | Markets, token decimals, and current Sonar quote readiness |
|
|
86
|
-
| `strata_quote` | Expected output, consumed input, fees, minimum output, price impact, and expiry |
|
|
87
|
-
|
|
88
|
-
### A Sonar quote call
|
|
89
|
-
|
|
90
|
-
```json
|
|
91
|
-
{
|
|
92
|
-
"market": "SOL/USDC",
|
|
93
|
-
"side": "sell",
|
|
94
|
-
"amountInAtoms": "10000000"
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
The result gives an agent the economics it needs to reason clearly:
|
|
99
|
-
|
|
100
|
-
```json
|
|
101
|
-
{
|
|
102
|
-
"provider": "Sonar",
|
|
103
|
-
"amount_in_consumed_atoms": "10000000",
|
|
104
|
-
"amount_out_atoms": "1990000",
|
|
105
|
-
"minimum_output_atoms": "1990000",
|
|
106
|
-
"output_fee_atoms": "995",
|
|
107
|
-
"reference_price": "199.1",
|
|
108
|
-
"price_impact_pct": "0.0005"
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
The values above use the repository's versioned example fixture. Live quotes
|
|
113
|
-
also include a unique quote ID and authoritative expiry.
|
|
114
|
-
|
|
115
|
-
Sonar handles the market. Your agent works with one economic result.
|
|
26
|
+
The tools currently available are:
|
|
116
27
|
|
|
117
|
-
|
|
28
|
+
- `strata_capabilities`
|
|
29
|
+
- `strata_action_graph`
|
|
30
|
+
- `strata_markets`, when `markets.read` is enabled for MCP
|
|
31
|
+
- `strata_quote`, when `quotes.read` is enabled for MCP
|
|
32
|
+
- `strata_execution_challenge`, when `trade.prepare` is enabled for MCP
|
|
33
|
+
- `strata_execution_prepare`, when `trade.prepare` is enabled for MCP
|
|
34
|
+
- `strata_execution_submit`, when `trade.submit` is enabled for MCP
|
|
35
|
+
- `strata_order_challenge`, when `orders.prepare` is enabled for MCP
|
|
36
|
+
- `strata_order_prepare`, when `orders.prepare` is enabled for MCP
|
|
37
|
+
- `strata_order_submit`, when `orders.submit` is enabled for MCP
|
|
118
38
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
39
|
+
Every initialization response carries the compact Strata Agent Harness. The
|
|
40
|
+
server also publishes the complete harness as the
|
|
41
|
+
`strata://agent-harness/v1` resource and provides a `strata_start` prompt for
|
|
42
|
+
applying it to one concrete objective.
|
|
43
|
+
The live executable topology is also available as
|
|
44
|
+
`strata://action-graph/v1`.
|
|
123
45
|
|
|
124
|
-
|
|
46
|
+
The tool list follows the live public policy. Every call rechecks that policy,
|
|
47
|
+
so a disabled capability stops immediately even if a client cached an older
|
|
48
|
+
tool list.
|
|
125
49
|
|
|
126
|
-
|
|
127
|
-
| --- | --- | --- |
|
|
128
|
-
| Start with | `https://api.stratabook.app/mcp` | `npx -y @stratabook/mcp` |
|
|
129
|
-
| Best for | Agents with remote MCP support | Desktop clients and local toolchains |
|
|
130
|
-
| You operate | Nothing | The local Node.js process |
|
|
131
|
-
| Strata market data | Live | Live |
|
|
50
|
+
## Hosted Streamable HTTP
|
|
132
51
|
|
|
133
|
-
|
|
52
|
+
The managed public endpoint is:
|
|
134
53
|
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
"mcpServers": {
|
|
138
|
-
"strata": {
|
|
139
|
-
"command": "npx",
|
|
140
|
-
"args": ["-y", "@stratabook/mcp"]
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
54
|
+
```text
|
|
55
|
+
https://api.stratabook.app/mcp
|
|
144
56
|
```
|
|
145
57
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
## Self-host Streamable HTTP
|
|
58
|
+
For a self-hosted or development process:
|
|
149
59
|
|
|
150
60
|
```sh
|
|
151
|
-
|
|
152
|
-
--transport http \
|
|
153
|
-
--host 127.0.0.1 \
|
|
154
|
-
--port 8787
|
|
61
|
+
strata-mcp --transport http --port 8787
|
|
155
62
|
```
|
|
156
63
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
## Built for exact automation
|
|
161
|
-
|
|
162
|
-
- Token values stay as atomic-unit decimal strings.
|
|
163
|
-
- Quote expiry and minimum output remain explicit fields.
|
|
164
|
-
- The tool set follows what Strata currently makes available.
|
|
165
|
-
- Errors include stable codes and retryability hints.
|
|
64
|
+
Place TLS and request limiting in front of `/mcp`. Loopback is the default bind;
|
|
65
|
+
the official MCP HTTP helper enforces Host validation for local installations.
|
|
166
66
|
|
|
167
|
-
`
|
|
168
|
-
|
|
67
|
+
`GET /health` is a readiness check, not a shallow process-liveness response. It
|
|
68
|
+
validates the live capability catalog against the bundled public contract and
|
|
69
|
+
agent harness. A stale SDK or incompatible contract therefore returns `503` and
|
|
70
|
+
blocks release activation. The same process serves the reviewed discovery
|
|
71
|
+
manifest at `/.well-known/strata-agent.json` and the graph at
|
|
72
|
+
`/.well-known/strata-action-graph.json`.
|
|
169
73
|
|
|
170
|
-
##
|
|
74
|
+
## Safety
|
|
171
75
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
-
|
|
175
|
-
|
|
176
|
-
|
|
76
|
+
The external agent owner decides what its agent may do and configures its
|
|
77
|
+
signer. MCP can request authorization bytes, prepare quote-bound trades or
|
|
78
|
+
resting-order controls, and submit the externally signed result. It accepts
|
|
79
|
+
public keys, detached signatures, and signed transactions, never private keys,
|
|
80
|
+
seed phrases, or wallet secrets. Amounts are token atoms encoded as base-10
|
|
81
|
+
strings.
|
|
177
82
|
|
|
178
|
-
|
|
83
|
+
Quotes default to zero execution tolerance. An agent can request a non-zero
|
|
84
|
+
`slippageBps` explicitly when its task accepts a lower minimum output; price
|
|
85
|
+
impact remains a separate measure of current market depth.
|
|
@@ -15,7 +15,7 @@ export declare const STRATA_AGENT_HARNESS: {
|
|
|
15
15
|
readonly manifest: "https://api.stratabook.app/.well-known/strata-agent.json";
|
|
16
16
|
};
|
|
17
17
|
readonly interfaces: {
|
|
18
|
-
readonly mcp_tool_order: readonly ["strata_capabilities", "strata_action_graph", "strata_markets", "strata_quote", "strata_execution_challenge", "strata_execution_prepare", "strata_execution_submit"];
|
|
18
|
+
readonly mcp_tool_order: readonly ["strata_capabilities", "strata_action_graph", "strata_markets", "strata_quote", "strata_execution_challenge", "strata_execution_prepare", "strata_execution_submit", "strata_order_challenge", "strata_order_prepare", "strata_order_submit"];
|
|
19
19
|
readonly terminal: readonly ["npx -y @stratabook/sdk capabilities --json", "npx -y @stratabook/sdk action-graph --json", "npx -y @stratabook/sdk markets --json", "npx -y @stratabook/sdk quote --market SOL/USDC --side sell --amount-atoms 10000000 --json"];
|
|
20
20
|
};
|
|
21
21
|
readonly workflow: readonly [{
|
|
@@ -50,7 +50,7 @@ export declare const STRATA_AGENT_HARNESS: {
|
|
|
50
50
|
readonly instruction: "Report consumed input, expected output, minimum output, fees by asset side, price impact, and remaining validity.";
|
|
51
51
|
}, {
|
|
52
52
|
readonly id: "authorize_writes";
|
|
53
|
-
readonly instruction: "When prepare and submit are exposed, keep signing external to Strata: request canonical authorization bytes, sign them with the owner-configured signer, verify the prepared transaction preserves the quote, then submit the externally signed transaction with idempotency.";
|
|
53
|
+
readonly instruction: "When prepare and submit are exposed, keep signing external to Strata: request canonical authorization bytes, sign them with the owner-configured signer, verify the prepared transaction preserves the quote or exact opaque order set, then submit the externally signed transaction with idempotency. Resting-order control uses place, cancel, or cancel-all and cancel-all is atomically bounded to six orders per call.";
|
|
54
54
|
}, {
|
|
55
55
|
readonly id: "monitor_outcome";
|
|
56
56
|
readonly instruction: "After an authorized submission, report the durable receipt or explicit failure. Never claim completion from preparation, signing, or an unconfirmed request.";
|
|
@@ -270,6 +270,57 @@ export declare const STRATA_ACTION_GRAPH: {
|
|
|
270
270
|
readonly summary: "Receive the execution ID, Solana signature, and submitted status.";
|
|
271
271
|
readonly required_capabilities: readonly [];
|
|
272
272
|
readonly available: true;
|
|
273
|
+
}, {
|
|
274
|
+
readonly id: "request_order_challenge";
|
|
275
|
+
readonly kind: "prepare";
|
|
276
|
+
readonly summary: "Bind a product-level place, cancel, or cancel-all operation to canonical authorization bytes.";
|
|
277
|
+
readonly required_capabilities: readonly ["orders.prepare"];
|
|
278
|
+
readonly available: false;
|
|
279
|
+
readonly operation: {
|
|
280
|
+
readonly method: "POST";
|
|
281
|
+
readonly path: "/v2/markets/{market_id}/orders/challenge";
|
|
282
|
+
readonly mcp_tool: "strata_order_challenge";
|
|
283
|
+
};
|
|
284
|
+
}, {
|
|
285
|
+
readonly id: "sign_order_authorization";
|
|
286
|
+
readonly kind: "external_signature";
|
|
287
|
+
readonly summary: "The agent owner's configured session signer verifies the exact order set and signs externally.";
|
|
288
|
+
readonly required_capabilities: readonly [];
|
|
289
|
+
readonly available: true;
|
|
290
|
+
}, {
|
|
291
|
+
readonly id: "prepare_order_control";
|
|
292
|
+
readonly kind: "prepare";
|
|
293
|
+
readonly summary: "Exchange the order authorization signature for a partially signed transaction.";
|
|
294
|
+
readonly required_capabilities: readonly ["orders.prepare"];
|
|
295
|
+
readonly available: false;
|
|
296
|
+
readonly operation: {
|
|
297
|
+
readonly method: "POST";
|
|
298
|
+
readonly path: "/v2/markets/{market_id}/orders/prepare";
|
|
299
|
+
readonly mcp_tool: "strata_order_prepare";
|
|
300
|
+
};
|
|
301
|
+
}, {
|
|
302
|
+
readonly id: "sign_order_transaction";
|
|
303
|
+
readonly kind: "external_signature";
|
|
304
|
+
readonly summary: "The external session signer verifies and fills only its transaction signature slot.";
|
|
305
|
+
readonly required_capabilities: readonly [];
|
|
306
|
+
readonly available: true;
|
|
307
|
+
}, {
|
|
308
|
+
readonly id: "submit_order_control";
|
|
309
|
+
readonly kind: "submit";
|
|
310
|
+
readonly summary: "Submit the unchanged signed order transaction with an idempotency key.";
|
|
311
|
+
readonly required_capabilities: readonly ["orders.submit"];
|
|
312
|
+
readonly available: false;
|
|
313
|
+
readonly operation: {
|
|
314
|
+
readonly method: "POST";
|
|
315
|
+
readonly path: "/v2/markets/{market_id}/orders/submit";
|
|
316
|
+
readonly mcp_tool: "strata_order_submit";
|
|
317
|
+
};
|
|
318
|
+
}, {
|
|
319
|
+
readonly id: "receive_order_receipt";
|
|
320
|
+
readonly kind: "receipt";
|
|
321
|
+
readonly summary: "Receive the opaque order IDs, transaction signature, and submitted status.";
|
|
322
|
+
readonly required_capabilities: readonly [];
|
|
323
|
+
readonly available: true;
|
|
273
324
|
}];
|
|
274
325
|
readonly edges: readonly [{
|
|
275
326
|
readonly from: "discover_capabilities";
|
|
@@ -351,7 +402,31 @@ export declare const STRATA_ACTION_GRAPH: {
|
|
|
351
402
|
readonly from: "submit_execution";
|
|
352
403
|
readonly to: "receive_receipt";
|
|
353
404
|
readonly condition: "the execution ID and idempotency key match";
|
|
405
|
+
}, {
|
|
406
|
+
readonly from: "discover_platform_markets";
|
|
407
|
+
readonly to: "request_order_challenge";
|
|
408
|
+
readonly condition: "orders.prepare is enabled and the market accepts order control";
|
|
409
|
+
}, {
|
|
410
|
+
readonly from: "request_order_challenge";
|
|
411
|
+
readonly to: "sign_order_authorization";
|
|
412
|
+
readonly condition: "the action and exact opaque order set match owner intent";
|
|
413
|
+
}, {
|
|
414
|
+
readonly from: "sign_order_authorization";
|
|
415
|
+
readonly to: "prepare_order_control";
|
|
416
|
+
readonly condition: "a valid external authorization signature is available";
|
|
417
|
+
}, {
|
|
418
|
+
readonly from: "prepare_order_control";
|
|
419
|
+
readonly to: "sign_order_transaction";
|
|
420
|
+
readonly condition: "the prepared transaction preserves the signed order bindings";
|
|
421
|
+
}, {
|
|
422
|
+
readonly from: "sign_order_transaction";
|
|
423
|
+
readonly to: "submit_order_control";
|
|
424
|
+
readonly condition: "orders.submit is enabled and the signed transaction is unmodified";
|
|
425
|
+
}, {
|
|
426
|
+
readonly from: "submit_order_control";
|
|
427
|
+
readonly to: "receive_order_receipt";
|
|
428
|
+
readonly condition: "the control ID and idempotency key match";
|
|
354
429
|
}];
|
|
355
430
|
};
|
|
356
431
|
export declare const STRATA_ACTION_GRAPH_URI = "strata://action-graph/v1";
|
|
357
|
-
export declare const STRATA_AGENT_HARNESS_INSTRUCTIONS = "Strata Agent Harness 1.0. Start every objective with strata_capabilities, then strata_action_graph, then strata_markets. Read strata://agent-harness/v1 and strata://action-graph/v1. The external agent owner controls permission and signer authority. Strata accepts public keys, detached signatures, and signed transactions, never private keys or seed phrases. Resolve the market, side, exact input atoms, and tolerance before strata_quote. Treat amounts as unsigned base-10 token atoms; check quote bindings, labelled fees, minimum output, and expiry. To execute: request a challenge,
|
|
432
|
+
export declare const STRATA_AGENT_HARNESS_INSTRUCTIONS = "Strata Agent Harness 1.0. Start every objective with strata_capabilities, then strata_action_graph, then strata_markets. Read strata://agent-harness/v1 and strata://action-graph/v1. The external agent owner controls permission and signer authority. Strata accepts public keys, detached signatures, and signed transactions, never private keys or seed phrases. Resolve the market, side, exact input atoms, and tolerance before strata_quote. Treat amounts as unsigned base-10 token atoms; check quote bindings, labelled fees, minimum output, and expiry. To execute or control a resting order: request a challenge, verify its quote or exact opaque order bindings, sign canonical authorization bytes externally, prepare, verify and sign the returned transaction externally, then submit with idempotency. Cancel-all is atomically bounded to six orders per call. Stop on ambiguity, unavailable capabilities, paused markets, unsupported contracts, inconsistent bindings, expiry, or missing signer authority.";
|
|
@@ -23,7 +23,10 @@ export const STRATA_AGENT_HARNESS = {
|
|
|
23
23
|
"strata_quote",
|
|
24
24
|
"strata_execution_challenge",
|
|
25
25
|
"strata_execution_prepare",
|
|
26
|
-
"strata_execution_submit"
|
|
26
|
+
"strata_execution_submit",
|
|
27
|
+
"strata_order_challenge",
|
|
28
|
+
"strata_order_prepare",
|
|
29
|
+
"strata_order_submit"
|
|
27
30
|
],
|
|
28
31
|
"terminal": [
|
|
29
32
|
"npx -y @stratabook/sdk capabilities --json",
|
|
@@ -75,7 +78,7 @@ export const STRATA_AGENT_HARNESS = {
|
|
|
75
78
|
},
|
|
76
79
|
{
|
|
77
80
|
"id": "authorize_writes",
|
|
78
|
-
"instruction": "When prepare and submit are exposed, keep signing external to Strata: request canonical authorization bytes, sign them with the owner-configured signer, verify the prepared transaction preserves the quote, then submit the externally signed transaction with idempotency."
|
|
81
|
+
"instruction": "When prepare and submit are exposed, keep signing external to Strata: request canonical authorization bytes, sign them with the owner-configured signer, verify the prepared transaction preserves the quote or exact opaque order set, then submit the externally signed transaction with idempotency. Resting-order control uses place, cancel, or cancel-all and cancel-all is atomically bounded to six orders per call."
|
|
79
82
|
},
|
|
80
83
|
{
|
|
81
84
|
"id": "monitor_outcome",
|
|
@@ -360,6 +363,69 @@ export const STRATA_ACTION_GRAPH = {
|
|
|
360
363
|
"summary": "Receive the execution ID, Solana signature, and submitted status.",
|
|
361
364
|
"required_capabilities": [],
|
|
362
365
|
"available": true
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
"id": "request_order_challenge",
|
|
369
|
+
"kind": "prepare",
|
|
370
|
+
"summary": "Bind a product-level place, cancel, or cancel-all operation to canonical authorization bytes.",
|
|
371
|
+
"required_capabilities": [
|
|
372
|
+
"orders.prepare"
|
|
373
|
+
],
|
|
374
|
+
"available": false,
|
|
375
|
+
"operation": {
|
|
376
|
+
"method": "POST",
|
|
377
|
+
"path": "/v2/markets/{market_id}/orders/challenge",
|
|
378
|
+
"mcp_tool": "strata_order_challenge"
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"id": "sign_order_authorization",
|
|
383
|
+
"kind": "external_signature",
|
|
384
|
+
"summary": "The agent owner's configured session signer verifies the exact order set and signs externally.",
|
|
385
|
+
"required_capabilities": [],
|
|
386
|
+
"available": true
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
"id": "prepare_order_control",
|
|
390
|
+
"kind": "prepare",
|
|
391
|
+
"summary": "Exchange the order authorization signature for a partially signed transaction.",
|
|
392
|
+
"required_capabilities": [
|
|
393
|
+
"orders.prepare"
|
|
394
|
+
],
|
|
395
|
+
"available": false,
|
|
396
|
+
"operation": {
|
|
397
|
+
"method": "POST",
|
|
398
|
+
"path": "/v2/markets/{market_id}/orders/prepare",
|
|
399
|
+
"mcp_tool": "strata_order_prepare"
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
"id": "sign_order_transaction",
|
|
404
|
+
"kind": "external_signature",
|
|
405
|
+
"summary": "The external session signer verifies and fills only its transaction signature slot.",
|
|
406
|
+
"required_capabilities": [],
|
|
407
|
+
"available": true
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
"id": "submit_order_control",
|
|
411
|
+
"kind": "submit",
|
|
412
|
+
"summary": "Submit the unchanged signed order transaction with an idempotency key.",
|
|
413
|
+
"required_capabilities": [
|
|
414
|
+
"orders.submit"
|
|
415
|
+
],
|
|
416
|
+
"available": false,
|
|
417
|
+
"operation": {
|
|
418
|
+
"method": "POST",
|
|
419
|
+
"path": "/v2/markets/{market_id}/orders/submit",
|
|
420
|
+
"mcp_tool": "strata_order_submit"
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
"id": "receive_order_receipt",
|
|
425
|
+
"kind": "receipt",
|
|
426
|
+
"summary": "Receive the opaque order IDs, transaction signature, and submitted status.",
|
|
427
|
+
"required_capabilities": [],
|
|
428
|
+
"available": true
|
|
363
429
|
}
|
|
364
430
|
],
|
|
365
431
|
"edges": [
|
|
@@ -462,8 +528,38 @@ export const STRATA_ACTION_GRAPH = {
|
|
|
462
528
|
"from": "submit_execution",
|
|
463
529
|
"to": "receive_receipt",
|
|
464
530
|
"condition": "the execution ID and idempotency key match"
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
"from": "discover_platform_markets",
|
|
534
|
+
"to": "request_order_challenge",
|
|
535
|
+
"condition": "orders.prepare is enabled and the market accepts order control"
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
"from": "request_order_challenge",
|
|
539
|
+
"to": "sign_order_authorization",
|
|
540
|
+
"condition": "the action and exact opaque order set match owner intent"
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
"from": "sign_order_authorization",
|
|
544
|
+
"to": "prepare_order_control",
|
|
545
|
+
"condition": "a valid external authorization signature is available"
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
"from": "prepare_order_control",
|
|
549
|
+
"to": "sign_order_transaction",
|
|
550
|
+
"condition": "the prepared transaction preserves the signed order bindings"
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
"from": "sign_order_transaction",
|
|
554
|
+
"to": "submit_order_control",
|
|
555
|
+
"condition": "orders.submit is enabled and the signed transaction is unmodified"
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
"from": "submit_order_control",
|
|
559
|
+
"to": "receive_order_receipt",
|
|
560
|
+
"condition": "the control ID and idempotency key match"
|
|
465
561
|
}
|
|
466
562
|
]
|
|
467
563
|
};
|
|
468
564
|
export const STRATA_ACTION_GRAPH_URI = "strata://action-graph/v1";
|
|
469
|
-
export const STRATA_AGENT_HARNESS_INSTRUCTIONS = "Strata Agent Harness 1.0. Start every objective with strata_capabilities, then strata_action_graph, then strata_markets. Read strata://agent-harness/v1 and strata://action-graph/v1. The external agent owner controls permission and signer authority. Strata accepts public keys, detached signatures, and signed transactions, never private keys or seed phrases. Resolve the market, side, exact input atoms, and tolerance before strata_quote. Treat amounts as unsigned base-10 token atoms; check quote bindings, labelled fees, minimum output, and expiry. To execute: request a challenge,
|
|
565
|
+
export const STRATA_AGENT_HARNESS_INSTRUCTIONS = "Strata Agent Harness 1.0. Start every objective with strata_capabilities, then strata_action_graph, then strata_markets. Read strata://agent-harness/v1 and strata://action-graph/v1. The external agent owner controls permission and signer authority. Strata accepts public keys, detached signatures, and signed transactions, never private keys or seed phrases. Resolve the market, side, exact input atoms, and tolerance before strata_quote. Treat amounts as unsigned base-10 token atoms; check quote bindings, labelled fees, minimum output, and expiry. To execute or control a resting order: request a challenge, verify its quote or exact opaque order bindings, sign canonical authorization bytes externally, prepare, verify and sign the returned transaction externally, then submit with idempotency. Cancel-all is atomically bounded to six orders per call. Stop on ambiguity, unavailable capabilities, paused markets, unsupported contracts, inconsistent bindings, expiry, or missing signer authority.";
|
package/dist/src/server.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import { StrataClient, type CapabilityCatalog } from "@stratabook/sdk";
|
|
2
|
+
import { StrataClient, StrataPlatformClient, type CapabilityCatalog } from "@stratabook/sdk";
|
|
3
3
|
export interface StrataMcpOptions {
|
|
4
4
|
apiBase?: string;
|
|
5
5
|
timeoutMs?: number;
|
|
6
6
|
client?: StrataClient;
|
|
7
|
+
platformClient?: StrataPlatformClient;
|
|
7
8
|
}
|
|
8
9
|
export interface StrataMcpRuntime {
|
|
9
10
|
server: McpServer;
|
package/dist/src/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import { DEFAULT_SLIPPAGE_BPS, StrataApiError, StrataClient, } from "@stratabook/sdk";
|
|
2
|
+
import { DEFAULT_SLIPPAGE_BPS, StrataApiError, StrataClient, StrataPlatformClient, } from "@stratabook/sdk";
|
|
3
3
|
import * as z from "zod/v4";
|
|
4
4
|
import { STRATA_AGENT_HARNESS, STRATA_AGENT_HARNESS_INSTRUCTIONS, STRATA_AGENT_HARNESS_URI, STRATA_ACTION_GRAPH_URI, } from "./generated-harness.js";
|
|
5
5
|
import { SERVER_VERSION } from "./version.js";
|
|
@@ -33,6 +33,10 @@ export async function probeStrataMcpReadiness(options = {}) {
|
|
|
33
33
|
}
|
|
34
34
|
export async function createStrataMcpServer(options = {}) {
|
|
35
35
|
const client = strataClient(options);
|
|
36
|
+
const platformClient = options.platformClient ?? new StrataPlatformClient({
|
|
37
|
+
apiBase: options.apiBase,
|
|
38
|
+
timeoutMs: options.timeoutMs,
|
|
39
|
+
});
|
|
36
40
|
const initialCatalog = await client.capabilities();
|
|
37
41
|
if (initialCatalog.contract_version !== STRATA_AGENT_HARNESS.contract_version) {
|
|
38
42
|
throw new Error("agent harness and live contract versions differ");
|
|
@@ -285,12 +289,133 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
285
289
|
const response = await client.executionSubmit(request);
|
|
286
290
|
return toolResult(response, `Submitted execution ${response.execution_id} as ${response.signature}.`);
|
|
287
291
|
}));
|
|
292
|
+
const orderChallenge = server.registerTool("strata_order_challenge", {
|
|
293
|
+
title: "Strata order challenge",
|
|
294
|
+
description: "Bind a product-level place, cancel, or cancel-all request to canonical bytes for the agent owner's external signer.",
|
|
295
|
+
inputSchema: {
|
|
296
|
+
marketId: z.string().regex(/^market_[0-9a-f]{32}$/),
|
|
297
|
+
action: z.enum(["place", "cancel", "cancel_all"]),
|
|
298
|
+
ownerWallet: z.string().min(32).max(44),
|
|
299
|
+
sessionPublicKey: z.string().min(32).max(44),
|
|
300
|
+
accountSequence: z.string().regex(/^[0-9]+$/).max(20).optional(),
|
|
301
|
+
clientOrderId: z.string().min(1).max(64).regex(/^[A-Za-z0-9._-]+$/).optional(),
|
|
302
|
+
side: z.enum(["buy", "sell"]).optional(),
|
|
303
|
+
orderType: z.enum(["good_until_cancelled", "post_only"]).optional(),
|
|
304
|
+
limitPriceAtoms: z.string().regex(/^[1-9][0-9]*$/).max(20).optional(),
|
|
305
|
+
sizeAtoms: z.string().regex(/^[1-9][0-9]*$/).max(20).optional(),
|
|
306
|
+
orderId: z.string().regex(/^order_[0-9a-f]{32}$/).optional(),
|
|
307
|
+
},
|
|
308
|
+
annotations: {
|
|
309
|
+
readOnlyHint: false,
|
|
310
|
+
destructiveHint: true,
|
|
311
|
+
idempotentHint: false,
|
|
312
|
+
openWorldHint: true,
|
|
313
|
+
},
|
|
314
|
+
}, async (args) => guardedTool(client, "orders.prepare", async () => {
|
|
315
|
+
let request;
|
|
316
|
+
if (args.action === "place") {
|
|
317
|
+
if (args.accountSequence === undefined
|
|
318
|
+
|| args.clientOrderId === undefined
|
|
319
|
+
|| args.side === undefined
|
|
320
|
+
|| args.orderType === undefined
|
|
321
|
+
|| args.limitPriceAtoms === undefined
|
|
322
|
+
|| args.sizeAtoms === undefined) {
|
|
323
|
+
return toolError("invalid_request", "Place requires accountSequence, clientOrderId, side, orderType, limitPriceAtoms, and sizeAtoms.", false);
|
|
324
|
+
}
|
|
325
|
+
request = {
|
|
326
|
+
action: "place",
|
|
327
|
+
ownerWallet: args.ownerWallet,
|
|
328
|
+
sessionPublicKey: args.sessionPublicKey,
|
|
329
|
+
accountSequence: args.accountSequence,
|
|
330
|
+
clientOrderId: args.clientOrderId,
|
|
331
|
+
side: args.side,
|
|
332
|
+
orderType: args.orderType,
|
|
333
|
+
limitPriceAtoms: args.limitPriceAtoms,
|
|
334
|
+
sizeAtoms: args.sizeAtoms,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
else if (args.action === "cancel") {
|
|
338
|
+
if (args.orderId === undefined) {
|
|
339
|
+
return toolError("invalid_request", "Cancel requires orderId.", false);
|
|
340
|
+
}
|
|
341
|
+
request = {
|
|
342
|
+
action: "cancel",
|
|
343
|
+
ownerWallet: args.ownerWallet,
|
|
344
|
+
sessionPublicKey: args.sessionPublicKey,
|
|
345
|
+
orderId: args.orderId,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
request = {
|
|
350
|
+
action: "cancel_all",
|
|
351
|
+
ownerWallet: args.ownerWallet,
|
|
352
|
+
sessionPublicKey: args.sessionPublicKey,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const response = await platformClient.orders.challenge(args.marketId, request);
|
|
356
|
+
return toolResult(response, `Order challenge ${response.challenge_id} binds ${response.order_ids.length} opaque order ID(s); expires at ${response.expires_at_ms}.`);
|
|
357
|
+
}));
|
|
358
|
+
const orderPrepare = server.registerTool("strata_order_prepare", {
|
|
359
|
+
title: "Prepare Strata order control",
|
|
360
|
+
description: "Exchange an externally signed order challenge for an immutable partially signed transaction.",
|
|
361
|
+
inputSchema: {
|
|
362
|
+
marketId: z.string().regex(/^market_[0-9a-f]{32}$/),
|
|
363
|
+
challengeId: z.string().regex(/^oc_[0-9a-f]{32}$/),
|
|
364
|
+
authorizationSignature: z
|
|
365
|
+
.string()
|
|
366
|
+
.min(64)
|
|
367
|
+
.max(88)
|
|
368
|
+
.regex(/^[1-9A-HJ-NP-Za-km-z]+$/),
|
|
369
|
+
},
|
|
370
|
+
annotations: {
|
|
371
|
+
readOnlyHint: false,
|
|
372
|
+
destructiveHint: true,
|
|
373
|
+
idempotentHint: false,
|
|
374
|
+
openWorldHint: true,
|
|
375
|
+
},
|
|
376
|
+
}, async ({ marketId, challengeId, authorizationSignature }) => guardedTool(client, "orders.prepare", async () => {
|
|
377
|
+
const response = await platformClient.orders.prepare(marketId, {
|
|
378
|
+
challengeId,
|
|
379
|
+
authorizationSignature,
|
|
380
|
+
});
|
|
381
|
+
return toolResult(response, `Prepared ${response.action} control ${response.order_control_id}; externally verify and sign before ${response.expires_at_ms}.`);
|
|
382
|
+
}));
|
|
383
|
+
const orderSubmit = server.registerTool("strata_order_submit", {
|
|
384
|
+
title: "Submit Strata order control",
|
|
385
|
+
description: "Submit an externally signed order transaction with a stable retry key.",
|
|
386
|
+
inputSchema: {
|
|
387
|
+
marketId: z.string().regex(/^market_[0-9a-f]{32}$/),
|
|
388
|
+
orderControlId: z.string().regex(/^or_[0-9a-f]{32}$/),
|
|
389
|
+
signedTransactionBase64: z
|
|
390
|
+
.string()
|
|
391
|
+
.min(4)
|
|
392
|
+
.max(8_192)
|
|
393
|
+
.regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/),
|
|
394
|
+
idempotencyKey: z.string().min(1).max(64).regex(/^[A-Za-z0-9._-]+$/),
|
|
395
|
+
},
|
|
396
|
+
annotations: {
|
|
397
|
+
readOnlyHint: false,
|
|
398
|
+
destructiveHint: true,
|
|
399
|
+
idempotentHint: true,
|
|
400
|
+
openWorldHint: true,
|
|
401
|
+
},
|
|
402
|
+
}, async ({ marketId, orderControlId, signedTransactionBase64, idempotencyKey }) => guardedTool(client, "orders.submit", async () => {
|
|
403
|
+
const response = await platformClient.orders.submit(marketId, {
|
|
404
|
+
orderControlId,
|
|
405
|
+
signedTransactionBase64,
|
|
406
|
+
idempotencyKey,
|
|
407
|
+
});
|
|
408
|
+
return toolResult(response, `Submitted ${response.action} control ${response.order_control_id} as ${response.signature}.`);
|
|
409
|
+
}));
|
|
288
410
|
const handles = {
|
|
289
411
|
markets,
|
|
290
412
|
quote,
|
|
291
413
|
executionChallenge,
|
|
292
414
|
executionPrepare,
|
|
293
415
|
executionSubmit,
|
|
416
|
+
orderChallenge,
|
|
417
|
+
orderPrepare,
|
|
418
|
+
orderSubmit,
|
|
294
419
|
};
|
|
295
420
|
applyCapabilityCatalog(handles, initialCatalog);
|
|
296
421
|
let closed = false;
|
|
@@ -321,6 +446,9 @@ function applyCapabilityCatalog(handles, catalog) {
|
|
|
321
446
|
setToolEnabled(handles.executionChallenge, capabilityAvailable(catalog, "trade.prepare"));
|
|
322
447
|
setToolEnabled(handles.executionPrepare, capabilityAvailable(catalog, "trade.prepare"));
|
|
323
448
|
setToolEnabled(handles.executionSubmit, capabilityAvailable(catalog, "trade.submit"));
|
|
449
|
+
setToolEnabled(handles.orderChallenge, capabilityAvailable(catalog, "orders.prepare"));
|
|
450
|
+
setToolEnabled(handles.orderPrepare, capabilityAvailable(catalog, "orders.prepare"));
|
|
451
|
+
setToolEnabled(handles.orderSubmit, capabilityAvailable(catalog, "orders.submit"));
|
|
324
452
|
}
|
|
325
453
|
function setToolEnabled(tool, enabled) {
|
|
326
454
|
if (enabled)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratabook/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Connect AI agents to Strata markets and Sonar quotes with MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT OR Apache-2.0",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
47
|
-
"@stratabook/sdk": "0.1.
|
|
47
|
+
"@stratabook/sdk": "0.1.5",
|
|
48
48
|
"zod": "^3.25.76"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|